I'm building a front-end to a mail-system. It's nicely split up in controllers and services. I'm using $interval to check for new mails, which gets received in JSON, and added to a model.
Everything gets rendered nicely to the screen with checkboxes to choose mails for deletions and buttons etc...
The problem is, that while a person is making choices - $interval will check for new mails, and replace the model-array with the incoming data, recreating the DOM and resetting all choices no matter if it contains new or the same data. The whole idea of the front-end is to avoid a user clicking "update" all the time.
I thought angular.copy could save me from headaches, but no... I read up on all kind of weird stuff about including dates in your model to diff between the incoming and existing model.
I can only come up with one solution for this problem, and that is to write functions myself that compare the incoming and existing array with all existing properties on both object. Fx. obj1.id == obj2.id then check properties, or add object if it doesn't exist.
I have been spoiled rotten in Knockout, because it deals with these kind of things. (when sending the same JSON array to an observable it will not recreate the dom - leaving my checkboxes/dom changes, alone).
Does anyone have a good solution for this problem or can anyone recommend a hack of some kind? I'm open to everything! I'm beyond desperate.
You can consider using transclusion inside a custom directive, to achieve the behavior you are looking for without using ng-repeat.
ng-options is the directive which is designed specifically to populate the items of a dropdown list. One major advantage using ng-options for the dropdown is, it allows us to pass the selected value to be an object. Whereas, using ng-repeat the selected value can only be string.
$first and $last It's common when using ng-repeat to add specific behavior to the first or last element of the loop, e.g. special styling around the edges. Instead, ng-repeat already supplies you with two ready boolean properties. $first is true for the first element, and $last is true for the last element.
However, some directives, such as ng-controller and ng-repeat, create new child scopes and attach the child scope to the corresponding DOM element.
I found a solution!
After poking around and further checking the "track by" with my scenarios, I can see that it actually does more what it says:
1) If you have a collection of objects, with each object having: id, name, description, you can, using 'track by' choose a property that it connects to, so, on retrieving a new collection of objects from a webservice, it will not render the DOM object belonging to the value.
2) Most importantly, and what I was after: If an object with an existing id arrives from the server with fx a changed name, will it be reflected in the array collection on the object with that id? Yes, it will! So, "track by" will actually check the properties of the incoming object and replace the old object and still leave the id alone. That's intense.
It's also worth noting that "track by" works also with other directives than ng-repeat, such as select.
I made a small demo, for other people who might be confused about how everything works... but it seems to be cool!
<div ng-repeat='country in countryArray track by country.id'>
{{country.id}}
{{country.name}}
<input type="checkbox"></input>
</div>
<div>
<select ng-model='nonExisting'
ng-options='country.name for country in countryArray
track by country.id'></select>
</div>
</div>
http://jsfiddle.net/KUf8C/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With