I'm using $watch to get a callback when an array changes. Sending true for the third param will detect when any part of any element changes. But I need to know when and which item has been added or removed. Is there a better way of decoding added/removed element than just doing a manual comparison?
I would like to know whether an item was added or deleted and easily get a reference to the item.
Related
By default, dom-repeat arrays only re-filter and re-sort when the array itself is mutated, or the item itself changes property that correspond to its observer: https://www.polymer-project.org/1.0/docs/devguide/templates.html#filtering-and-sorting-lists.
Is there anyway to trigger sorting function when the sorting function itself change? For example, when you want to change from increasing order to decreasing order, a.k.a changing sorting function.
Try calling render on the dom-repeat.
From the source code documentation:
In order to re-run the filter or sort functions based on changes to sub-fields
of items, the observe property may be set as a space-separated list of
item sub-fields that should cause a re-filter/sort when modified. If
the filter or sort function depends on properties not contained in items,
the user should observe changes to those properties and call render to update
the view based on the dependency change.
I've seen a lot of questions about the order in which ng-repeat finishes compared to other directives or things going on in Angular land, but I haven't been able to find an answer to how exactly it accomplishes this.
I have two ideas of how it could work.
First Way:
When ng-repeat's watcher triggers, it removes all elements it created from the DOM then creates all new elements in their place, even if many of those elements are the same (e.g. in the case of 1 item added to the backing array).
Second way: Since ng-repeat already keeps track of which elements go with which items in its backing collection, it simply removes the items that no longer exist in the collection and creates new elements for items that are new to the collection.
Which is it and why?
It's the second way: Angular tries to be smart about creating/removing DOM elements:
The ngRepeat directive provides a way to render a collection of items given a template. To do this, AngularJS compiles the given template and then clones it for each unique item in the collection. As the collection is mutated by the Controller, AngularJS adds, removes, and updates the relevant DOM elements as needed.
But, how does AngularJS know which actions to perform when? If you start to test the rendering, you'll discover that AngularJS doesn't brute force DOM creation; that is, it doesn't recreate the DOM for every rendering. Instead, it only creates a new DOM element when a completely new item has been introduced to the collection. If an existing item has been updated, AngularJS merely updates the relevant DOM properties rather than creating a new DOM node.
This can still impact performance unnecessarily, i.e. when passing elements by-value in a collection (there's an excellent example of this in the blog post linked above). That's why Angular supports "track by" for ngRepeat since version 1.2: It's a way to help Angular decide when DOM creation is necessary:
With this association in place, AngularJS will not $destroy and re-create DOM nodes unnecessarily. This can have a huge performance and user experience benefit.
The official documentation states:
You can also provide an optional tracking function which can be used to associate the objects in the collection with the DOM elements. If no tracking function is specified the ng-repeat associates elements by identity in the collection.
For example: item in items track by item.id is a typical pattern when the items come from the database. In this case the object identity does not matter. Two objects are considered equivalent as long as their id property is same.
I have a similar issue to what is stated in the 2 posts below - I have 3 ng repeats in a partial, when I update the source arrays the changes are not reflected in the view.
ng-repeat's element not updated on array modification
AngularJS not refreshing ngRepeat when updating array
The ng repeats are within 3 ul's with each listing out input checkboxes with ng click on each, if I check an input from the the first list then my js code runs through the other 2 arrays, finds matching inputs and sets a property called IsSelected to true which is bound to ng checked of each input. e.g regions in the first list - if I check europe, then it checks all the European countries in the second list, and all the related cities in the 3rd list when I click on an apply button. $scope.$apply() after the js code for setting IsSelected doesnt work, but if I set the arrays to null then the view appears empty for that particular list. I then tried to use track with a property that constantly changes when I update the array elements like a guid but that also doesnt work. If it was a scope issue then why would setting the array to null then update the view as suspected?
I can add element to tree in extjs and I want to see it just after adding. How can I focus on than element (expand everything before it and put selection on it)?
You can use the method selectPath on your TreePanel as detailed here:
http://docs.sencha.com/extjs/4.2.0/#!/api/Ext.tree.Panel-method-selectPath
This method will open every nodes needed to access your element and select this element. The way you express the path is as follow:
Ext.getCmp('treePanel').selectPath('/Root/Leaf/Element', 'text')
Here, the text property of my TreeModel has been used (The second parameter), but you can change that for anything, like the id.
Ext.getCmp('treePanel').selectPath('/1/16/42', 'id')
To build this path, the better way is to use the method getPath on the particular item you want to select:
item.getPath('text')
Showing an example will likely make more sense than trying to explain this. Please reference this http://plnkr.co/edit/ipGYEX?p=preview as it ALMOST does exactly what I need.
In the example, click Add to create a new select menu and choose an option. This should add it to the parent form. Currently I'm handling this aspect with an $emit. The core problem is that I can't find a way to assign $index to each select. I'd like to attach it to the model name in order to make each one unique. However, simply doing something like ng-model="selectNum{{$index}} causes an error when passed through attrs.ngModel. As is, the ngModel is repeated for each dropdown that's added and thus, every time the form gets overwritten. I WANT to add each select as a unique object to the form - and update that specific instance should the associated select change.
Can anyone provide some insight on how to either attach the $index or perhaps another way of updating the form?
Not a direct answer to getting the values into the form object, but here's an option similar to something I'm doing for a very similar situation:
http://plnkr.co/edit/uEHFWgRQ9fP2gpeWuE5y?p=preview
Basically storing the values within the elements of the array being repeated on, then I use that object from the model for a post to the server.