Angular: Change classes of elements by clicking one, inside ng-repeat - angularjs

There is ng-repeat and in there are many li's. The superior li's are visible, while the minor ones are not displayed. By clicking on one superior li, the minor should get visible/invisible. All li's are equated in their code, means there is no embedding code which purport who is superior or minor. They are only distinguishable by id. A superior li's has the id 1, while a minor get's the id 1.1.
<li class="list-table" ng-repeat="row in rows" id="{{row.first}}.{{row.second}}" ng-click="toggle_rows(row)")
<div style="list-cell">
<p>{{row.first}}</p>
<p>{{row.second}}</p>
<p>{{row.name}}</p>
<div>
</li>
I tried several things but got stuck. Any advice appreciated! Thanks in advance!

Related

ng-repeat view "lagging" behind the actual model?

HTML:
{{vm.regions}}
<div ng-repeat="region in vm.regions">
{{region}}
</div>
On button presses, the model a.k.a vm.regions gets updated in the controller. For example vm.regions = [].
I can see that the array {{vm.regions}} is instantly updated, but the elements in the div take at least a second to update, meaning you can see old elements for a bit in the newly updated list, for example.
What is causing this?
It is in AngularJs Best Practices to always add "track by $index" in order to inprove performances.
{{vm.regions}}
<div ng-repeat="region in vm.regions track by $index">
{{region}}
</div>
Link : https://docs.angularjs.org/api/ng/directive/ngRepeat
Try using vs-repeat. It applies virtual scrolling to ng-repeat which increases its performance drastically even if you are not using one time binding.
http://kamilkp.github.io/angular-vs-repeat/#?tab=8

Polymer 1.0 itemForElement in nested dom-repeat

For example, I have a dom-repeat like this:
<template is="dom-repeat" id="rows" items="[[rows]]" as="row">
<tr class="result-tb-row" closed$=[[row.closed]]>
<td class="result-tb-data">
<ul class="violation-list">
<template id="rowItem" is="dom-repeat" items="[[row.items]]">
<li on-click="click">[[item]]</li>
</template>
<ul>
</td>
</tr>
</template>
If I want to know which row I am clicking on, I can write a something like this:
this.$.rows.itemForElement(event.target);
However, what if I want to get the exact item corresponding to li I clicked on. How do I do so? I obviously cannot do this.$.rowItem.itemForElement(event.target) because rowItem isn't unique.
Update
event.model.item seems to solve this particular problem. But if you have double nested dom-repeat or more and you want to get the middle layers, you're out of luck. Probably have to implement an iterator yourselves. double nested dom-repeat happens a lot in table. Table is already a nested dom-repeat; if you want a dom-repeat inside a table cell (and you will run into it), double nested dom-repeat happens.
It isn't hard to implement an iterator, just hope that the Polymer team supports more methods for nested dom-repeat because this is an awesome feature.
event.target holds a <li> reference.
When you do this.$.rowItem.itemForElement(event.target), the dom-repeat named rowItem is unique, and it will look what item belongs to that <li>.
But if you just want item data, you can use event.model.item, which holds a reference to the item data that belongs to the line you clicked.
This is a perfectly valid question, I'm facing the same situation. Anyone has a solution?
UPDATE
I found the ID in e.model.__data__. But this feels like a hack
Here it is. It took me a couple of apps to figure this out.
Polymer considers the inner ID to be a dynamically created ID. So using Polymer's automatic node finding for dynamic IDs, you can say:
this.$$('#rowItem').itemForElement(event.target)
As documented here:
https://www.polymer-project.org/1.0/docs/devguide/local-dom.html#node-finding

quick-ng-repeat does not update view

I use quick-ng-repeat Quick-ng-repeat for my list to iterate because it is a huge list and I would improve performance.
Now I recognized that if I change the model, the view is not updated with this code:
<span quick-ng-repeat="item in collection track by $index" quick-repeat-list="items">
{{ item }}
</span>
With this code
<span ng-repeat="item in collection track by $index">
{{ item }}
</span>
every works fine.
Does anyone have any idee why this happens?
Thanks a lot!
quick-ng-repeat does not implement deep watch just like ng-repeat, it implement one way binding approach. So if your model changes frequently, don't use it.
In Angular 1.2 a new addition was made to the syntax of ngRepeat: the amazingly awesome track by clause. It allows you to specify your own key for ngRepeat to identify objects by, instead of just generating unique IDs.
This means that you can change the above to be ng-repeat="task in tasks track by task.id" and since the ID would be the same in both your original tasks and the updated ones from the server – ngRepeat will know not to recreate the DOM elements and reuse them
The Quick ng-repeat is doing one way binding ,it something similar to what we do in angularjs
<div ng-repeat="item in ::items">{{item.name}}</div>
This does not create unnecessary watches.
I think Quick-ng-repeat use Single binding same as in angular 1.4 like (::).Single binding mean it will be create a watcher for your repeat that why it will not effect when object is change.
<div ng-repeat="obj in ::objList">{{obj.name}}</div>

DOM recreation performance problems with nested ng-repeat

I'm rendering a calendar UI with AngularJS and I'm running into some pretty big performance issues when flipping through the weeks. Let me explain.
The UI looks something like this:
I loop over all the persons, then for each person I loop over the days, and then render the calendar objects for that user for that day. Something like this (simplified):
<div ng-repeat="user in ::ctrl.users track by user.id" class="row">
<div ng-repeat="day in ctrl.days" class="cell">
<div ng-repeat="item in ctrl.items[user.id][day] track by item.id">
<div class="item">
There are not a crazy amount of watcher on this page (about 500), almost everything is bind-once.
The problem is when the user clicks the prev/next buttons to load the previous or next week. This changes the ctrl.days array with new days, and all the correct items are loaded. This performs fine until you have a ton of people and calendar items. Then all the destroying and recreating of DOM elements is really slow.
I came across the sly-repeat directive which is meant to cache and reuse DOM elements but because my outer ng-repeat changes (ctrl.days), the inner ng-repeat (with the items) is also recreated. So it doesn't really work.
How can I solve this problem? Right now browsing through the weeks with a large data-set takes about 2 seconds, which is of course not acceptable. With a small set of users and calendar items everything is super snappy.
Try using track by in your nested ng-repeats. This will prevent them from reloading unnecessary inner repeats. For more information, see:
http://www.codelord.net/2014/04/15/improving-ng-repeat-performance-with-track-by/

Is there a way to stop angularjs from watching a variable for changes?

I have a variable I need to put in a template, but it's only created and never updated or removed. It is, however, referenced in multiple areas of the template. It's used in ng-repeat, so it's an object. Not sure if that matters.
But I want to reference the variable once and stop angularjs from watching it. Is this possible?
Are you familiar with bind once?
Angular internally creates a $watch for each ng-* directive in order to keep the data up to date, so in this example just for displaying few info it creates 6 + 1 (ngRepeatWatch) watchers per person, even if the person is supposed to remain the same once shown. Iterate this amount for each person and you can have an idea about how easy is to reach 2000 watchers. Now if you need it because those data could change while you show the page or are bound to some models, it's ok. But most of the time they are static data that don't change once rendered. This is where bindonce can really help you.
https://github.com/Pasvaz/bindonce
<ul>
<li bindonce ng-repeat="person in Persons">
<a bo-href="'#/people/' + person.id"><img bo-src="person.imageUrl"></a>
<a bo-href="'#/people/' + person.id" bo-text="person.name"></a>
<p bo-class="{'cycled':person.generated}" bo-html="person.description"></p>
</li>
</ul>

Resources