DS.attr() isn't marked dirty, can't rollback - ember.js

I'm using a DS.attr() data type in one of my Ember-Data models (note, no attribute type specified) to allow me to store nested JSON data. For the most part, it works fine, however, when I make changes (e.g. with an input bound to one of its properties) the record isn't marked as 'modified' in the Ember inspector, although the view bindings are all working properly (i.e. if I echo the same property as text, it changes when the input changes). Similarly, after making a change to one of these properties, if I call the rollback() function on the model, the data isn't rolled back.
Of course, the regular properties work just fine, so I'm assuming this has something to do with the DS.attr() type not being specified.
Is there a way to make this work efficiently? I would try to use embedded records, but this data doesn't use any record IDs.
Thanks

To answer my own question, the best solution I've been able to come up with is to use the ember-data.model-fragments addon. It's pretty slick, and solves both problems that I listed above.

Related

Ember: Edit model object without setting isdirty

This topic har been discussed on stackoverflow before, but not with latest version of ember data, I think. At least none of the suggestions I have found have worked for me.
I use the latest version of Ember and Ember data (versjon 2.13.0). I use the JsonApiAdapter.
Scenario
After I load a record from the server I want to do a few changes to some of its properties. These changes shall not make the record dirty, and the changed attributes shall not show up in the record.changedAttributes(). Any changes the user may do after that shall make the record dirty.
Searching for a solution
I have tried to manually change the isDirty flag, but it didn't do it. I have also tried to find the place in the ember data code that sets the state after a record has been loaded (because essentially I am trying to do the same thing) but I haven't found where it is.
I have also tried record.send('pushedData'), but I didn't change anything of the state of the record.
Any help appreciated.
I know 3 methods which allow to modify server's response without dirtying records:
You can override adapter's handleResponse method and make modifications right in payload.
You can override serializer's normalize method.
You can load records from server with Ember.$.ajax method, modify response and then pass it to store's pushPayload method.
First two methods are good if you need to modify record after every load from server (no matter from what route/controller you do it). Both adapter and serializer can be model-specific. If you need to do it in only one place (controller or route), or if you need an access to route's/controller's variables - 3rd method is good.
I'm not aware about any way to mark record as dirty/not dirty. If you modify a record after it was stored, it becomes dirty.

Passing parameters between routes in Ember 2.x

While going from one route to another, I want to pass some data (especcially arrays). How is it possible?
Why can't we use query-params with arrays?
Is it a problem storing data in a specific service during transition?
Note:
I know there are some old questions those are nearly the same with this question. But their selected answers are no more applicable for Ember 2.x. Those questions are: 1, 2.
I´m not sure if queryparams won´t work with arrays as I only used it with single ids, but it would not be a good solutions even if it worked, there´s a limit on how much you can send by parameters and you should not bother any user with your data.
Just create a model to save your data for local use, so you can simply use the ember store
Use a service you´ll have to inject in every controller you want to use your data
I would prefer the model/store variant so you´ll be able to observe and just follow the normal flow which is also good if someone else has to maintain your code.
UPDATED
After testing with "transition.data"; not updating the history seems as a problem for us. So we again use "queryParams". The constraint is: do not pass a complex object between routes
OLD ANSWER
I'm using transition object for this purpose in an action while routing as the following:
let transition = router.transitionTo(route, model);
transition.data[propName] = propValue;
Also I wrote a component to use this code as link-to.

Determining which attributes were modified in an ember-data model

Is there any way of telling exactly which attributes were changed on a dirty record using ember-data?
The docs show a changedAttributes method, but I can’t use that directly because I want to bind it in a template.
I could set up observers for every field to get an event when they are updated, but that seems like a tedious solution, I was wondering if there was an easier way.
Edit: My use case is basically that I'm trying to indicate which fields were modified in an "edit" form.
There is an object _attributes on the record that has all the modified properties/values, you could use Em.keys on it for them all.

How to show all the data changes since the last commit in Ember data?

I know that Ember data's model has the isDirty attribute, but how can I use it to show a list of all the changes/deltas of the data since the last commit?
Tom Dale's talk (listen until 36:44) mentioned that it is possible to tweak the adapter(github, api) or serializer (github, api) hooks to do that. Can anyone give me an example?
current research: I'm using the local storage adapter which adds stuff to the dirty set, which I think might be what I want. It is found in the ember data store, ember data adapter, ember data relationship changes. I am trying to figure out how everything fits together to show the data changes.
If it's any help, Ember Data stores the new (unsaved) values of attributes in the model's _attributes hash. It's quite internal though so you might want to be careful with it - I would n't recommend manipulating it directly.

Backbone, selectively render parts in template

I am listing products as table rows, each row contains input fields for specifying the quantity of products.
I made a Fiddle for it here, http://jsfiddle.net/kroofy/4jTa8/19/
As you can see, after the input in the Qty field have been made, the whole row render again. And because of that the focus of the input field will be lost, which is not good if you want to input more than just one digit, or tab between input fields.
What would be the most elegant way to solve this?
I would handle this by setting model.set({qty: _qty}, {silent: true}) and then updating the non-input fields with this.$.
As an alternative to the silent treatment: rather than listening for change events, listen for change:qty and change:sellPrice and have a method that updates just the HTML that needs updating within this.$, rather than re-rendering the DOM object and breaking your focus.
Either way, your comment about "selective updating" on the fiddle is certainly the right way to go.
(this.$ is a backbone hack to jQuery that restricts all selectors to search only within the DOM of the View's element. The element doesn't even need an ID or class; it just needs to exist and the View maintains a handle to it. It's incredibly useful.)
i built a plugin for backbone called Backbone.ModelBinding that may be able to help in this situation. my plugin allows you to update portions of a view with data from a model, when the model changes.
i've forked / updated your fiddle to show it in action: http://jsfiddle.net/derickbailey/FEcyF/6/
i removed the binding to the model change. i've also added id attributes to the inputs of the form to facilitate the plugin (the attribute that the plugin uses is configurable, though). and lastly, i've added a data-bind attribute to the sell price total td.
you can get the plugin here: http://github.com/derickbailey/backbone.modelbinding/
hope that helps
FWIW: my plugin is an automated version of what Elf is suggesting. I've written code exactly like he is describing, numerous times, which is where the plugin came from. I just got tired of writing that code by hand :)