track by $index isn't solving dupes error - javascript

I am trying to iterate through an array of objects and display them in my HTML using Angular. I have done this before without any problems by using "track by $index". But the standard error is still raised:
Error:
[ngRepeat:dupes] http://errors.angularjs.org/1.3.15/ngRepeat/dupes?p0=(key%2C%20value)%20in%20n&p1=string%3Ab&p2=b
But I have already added track by $index. I am confident there isn't any issue requesting the data as I have been able to display it correctly.
<div ng-repeat="n in post.userData.bookmarks track by $index" >
<div ng-repeat="(key, value) in n">
<div>{{ key }}</div>
</div>
</div>
Suggestions?
Dataset:
bookmarks: [{"1234": "Title1"}, {"5678": "Title2"}]
What happens is that a user bookmarks a post that they want to read later. I save the post id and the title of the post to an object and store this in an array. (I actually just wanted to store it to an object like so: {"1234": "Title1", "5678": "Title2"}, but couldn't figure it out with mongodb, since it doesn't seem to let you save as object data type.)
Then I want to ng-repeat the user's bookmarks in their profile. The only way I know how to do this is to iterate through the array and then iterate through each object. Of course, there is only one item in each object. But this is why I have the second ng-repeat. But when I do track by $index for both, as one of the answers lists below, it still doesn't give the desired behavior.
Something that could be causing a problem is that I also have a sort of dashboard that can be viewed on the side while viewing any given post. And on the dashboard they should be able to see their bookmarks. Also if they are on a post that they have bookmarked, if they click a (un)bookmark button on the post, it should automatically remove that bookmark on their bookmark dashboard.
But none of the suggestions have worked.

You forgot another ng-repeat: <div ng-repeat="(key, value) in n track by $index">

I don't know Why u write two times repeat
<div ng-repeat="n in post.userData.bookmarks track by $index" >
<a ng-href="/tuts/{{n.key}}">{{ n.key}}</a>
</div>
OR
<div ng-repeat="(key,value) in post.userData.bookmarks track by $index" >
<a ng-href="/tuts/{{value}}">{{ value}}</a>
</div>
key is anything which you get from object.

Related

If all array items are hidden show another div in AngularJS

I'm using ng-repeat on my page. ng-class working very well.
<div class="card news" ng-repeat="item in news track by $index" id="{{news.nid}}" ng-init="parentIndex = $index" ng-class="{hidden: '{{getCheck($index)}}' == 'true'}">
...
</div>
Now I need, if all items are hidden, show this div:
<h3 class="news-empty">No news</h3>
Whats the rules? How can I do it? Thanks.
You need another method that checks if all elements are hidden:
$scope.everythingIsHidden = function() {
return $scope.news.every((new, index) => $scope.getCheck(index));
}
$scope.getCheck = function(index) { // Your getChek function that I suppose it checks if an element is hidden based on index
//...
}
<h3 class="news-empty" ng-if="everythingIsHidden()">No news</h3>
TheCog's answer will work. If you want to do this in a more 'Angular' way you're going to need to refactor what you have.
You shouldn't be trying to hide them with a CSS class. ngRepeats have a built in filter syntax. So, you should be filtering them out.
<div class="card news"
ng-repeat="item in news | filterMethod as results track by $index"
id="{{news.nid}}"
ng-init="parentIndex = $index"
>
<h3 class="news-empty" ng-if="results.length === 0" >No news</h3>
The as results statement in the repeat will store the filtered array in results. filterMethodneeds to be an angular filter and it will probably work similarly to your getCheck($index) method.
You want to add an ngShow to the h3 tag, and aim it at a function you write in your controller that checks if the array is empty, probably by iterating over the same array that's hidden and running getCheck($index) on each.

Angular: one-time binding, recompiling of nested ng-repeat

I am using one-time binding and kcd-recompile, but have a problem with nested ng-repeat. Let's assume the code looks like this:
<div ng-repeat="person in ::people">
<div ng-repeat="friend in ::person.friends" kcd-recompile="person.friends">
{{friend.name}}
</div>
</div>
If I add a friend to one of the people now, I want this person div to be recompiled without recompiling the other people's divs. The problem is: person.friends is only updated, if person is updated.
So it works if I add the kcd-recompile to the first ng-repeat, but then every person's div is recompiled (which I want to prevent).
Is there any possibility to update person without recompiling the whole first ng-repeat?
Found a solution on my own (after hours), if anyone needs it:
Using people[$index].friends instead of person.friends, it works!
<div ng-repeat="person in ::people">
<div ng-repeat="friend in people[$index].friends" kcd-recompile="person.friends">
{{friend.name}}
</div>
</div>

ng-repeat uknown number of items

Okay this seems fairly odd but i am allowing my users to create any number of category / subcategories they want
When i pull the category data out it might look something like this:
as you can see from the above example the sub categories can have subcategories this list tree could go on forever.
Now trying to make the menu i have a simple list:
<ul class="nav dker">
<li ui-sref-active="active">
<a ui-sref="app.ui.jvectormap" href="#/app/ui/jvectormap">
<span translate="aside.nav.components.ui_kits.VECTOR_MAP" class="ng-scope">Vector Map</span>
</a>
</li>
</ul>
The issue here is that i don't know how many times i have to repeat the subcategories which makes it impossible for me to know when to check for it?
i hope you know where im going with this how can i make a reliable list that follows the array pattern above when i don't know how many levels there are?
You are going to want to create a recursive template which will essentially look something like this:
<div data-ng-include="'displaySubcategory.html'"></div>
where displaySubcategory.html contains the ng-repeat and a recursive call to itself.
<div data-ng-repeat="category in category.subcategories">
<h1>{{category.name}}</h1>
<div data-ng-include="'displaySubcategory.html'"></div>
</div>
The idea is that everytime you call ng-repeat you are creating a scope around the child element, so a call to {{category}} will display the lowest level (current child) of the tree/data structure.

data-binding not working on nested ng-repeat

When nesting ng-repeat it seems that clicking on the toggle button updates that addon in EVERY 'pair' (the first ng-repeat). Can anyone explain to me why this is the case and what I can do to fix it? Check the link above for the custom directive code...
<div ng-repeat="pair in pairs track by $index">
<h3>Pair {{ $index + 1}}</h3>
<div class='fieldrow'>
<button ng-repeat="addon in addons track by $index" toggle-button="addon.added">{{addon.name}} (£{{addon.price}})</button>
</div>
</div>
What is pair and what is addon, and how are they related. Right now, even though you have a nested ng-repeat, you have completely independent data structures, so addons array is same for each pair. Trott.
Based on this insight, I changed ng-repeat="addon in addons track by $index" to ng-repeat="addon in pair.addons track by $index"
Problem solved, thanks!
I think your code does not have any problem. see plunker here.
this code is working well:
<div ng-repeat="pair in pairs track by $index">
<h3>Pair {{ $index + 1}}</h3>
<div class='fieldrow'>
<button ng-repeat="addon in addons track by $index" toggle-button="addon.added">{{addon.name}} (£{{addon.price}})</button>
</div>
</div>

AngularJS : nested ng-repeat peformance

I have a requirement where data is dynamic and very hierarchical (3- 4 level deep) where each inner level can be a list which can again contain list (please look at my template below). Everything looks good in terms of performance upto 2 ng-repeat but performance degrade sharply for level 3 onwards ng-repeat.
<div class="struct-property">
<div ng-repeat="structGroup in triple.properties track by $index">
<div ng-repeat="props in structGroup track by $index">
<simpleproperty triple="props"></simpleproperty>
<multiplevalueproperty triple="props"></multiplevalueproperty>
<div ng-if="props.isStructProperty">
<div class="struct-property">
......
<div ng-repeat="structGroupInner in props.properties track by $index">
<div ng-repeat="propsInner in structGroupInner track by $index ">
<simpleproperty triple="propsInner"></simpleproperty>
<multiplevalueproperty triple="propsInner"> </multiplevalueproperty>
</div>
</div>
</div>
</div>
Please Note: that I have only static data
I used "track by" but not sure if I used it correctly. I did tried to log if DOM is getting recreated with children ng-repeat and I do see that with every nested ng-repeat, parent DOM is getting regenerated and thats the reason performance is very bad.
I also tried to refactor my data so that I can avoid nested ng-repeat but unfortunately I cannot refactor it further because it as a RDF-JSON representation.
Thanks in advance!

Categories

Resources