ng-repeat uknown number of items - javascript

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.

Related

track by $index isn't solving dupes error

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.

How to bind desIndex to sort values in angular-ui-tree?

I'm using angular-ui-tree.
The object I have in my treeview has a sort index. I am looking for a way to bind this sort index to the desIndex of the treeview scope, using something similar to this:
ui-tree-desIndex="node.sortIndex"
desIndex is the treeview node's index and node.sortIndex is my object's index.
I want it to sort my list by my objects' values, and when I move an object in the treeview the scope will update that object's index like this:
<div ui-tree="treeOptions" callbacks="treeOptions">
<ol ui-tree-nodes="" data-nodrop-enabled="true" ng-model="rootNodeLst" callbacks="treeOptions" id="tree-root">
<li ng-repeat="node ui-tree-desIndex="node.sortIndex" in rootNodeLst" callbacks="treeOptions" ui-tree-node ng-include="'nodes_renderer.html'"></li>
</ol>
</div>
The code above isn't working, how can I fix it?
Change this
<li ng-repeat="node ui-tree-desIndex="node.sortIndex" in rootNodeLst" callbacks="treeOptions" ui-tree-node ng-include="'nodes_renderer.html'"></li>
To this
<li ng-repeat="node in rootNodeLst" ui-tree-desIndex="node.sortIndex" callbacks="treeOptions" ui-tree-node ng-include="'nodes_renderer.html'"></li>
For starters, to get your ng-repeat working.
Then, if ui-tree-desIndex does not get the value set, you can try:
ui-tree-desIndex="{{node.sortIndex}}" or ng-attr-ui-tree-desIndex="{{node.sortIndex}}"
See this JSFiddle.
Funny thing.
Found out that the way im building the treeview with the nested html modify my $index to show this sort number, so, anyway. thanks for your time and helÄ

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>

Trigger function on a certain element - ngrepeat - angularjs

Good morning,
I'm trying to change the limitTo filter on a certain list, my issue is:
when I click to the trigger who change the filter limit the filter changes on all ng-repeated categories.
my function inside the main controller
$scope.showMore = function(limit) {
if($scope.limitItems === $scope.itemsPerList) {
$scope.limitItems = limit;
$scope.switchFilterText = 'less';
} else {
$scope.switchFilterText = 'more';
$scope.limitItems = $scope.itemsPerList;
}
}
my scenario (I rewrote it in a simplified version)
<li ng-repeat="item in category.items | limitTo: limitItems ">
{{item.title}}
</li>
<li ng-if="limitItems < (category.items.length)">
<a ng-click="showMore(category.items.length)" >Show {{ switchFilterText }}</a>
</li>
Could you explain me what's wrong with me?
I searched how to select a single element to apply the function but I didn't find anything useful
Update:
I found the way to solve my issue in this way:
No functions inside the controller are involved to make this functionality works properly:
<li ng-repeat="category in maincategories" ng-init="limitItems = maxItemsPerList">
{{category.title}}
<ul>
<li ng-repeat="item in category.items | limitTo: limitItems "> {{item.title}}
</li>
</ul>
<a ng-click="limitItems = category.items.length" href>
<b ng-if="category.items.length > maxItemsPerList && limitItems != category.items.length "> Show more </b>
</a>
I'm not really convinced about Angular (I used it in my past and I was impressed by the performance but now I can see logics senseless):
What I learned:
ng-if and ng-click cannot be used in the same content because ng-if creates new scopes so if you put ng-if on top of the "show more" link it will break the code
ng-init cannot be used in the same element of the ng-repeat otherwise the var initialised will not be available inside the ng-repeat block
I think there is another way to do that, maybe more clean but in this specific case I can't do a lot.
ng-if and ng-click cannot be used in the same content because ng-if
creates new scopes so if you put ng-if on top of the "show more" link
it will break the code
Yes, ng-if creates a new scope, but it is possible to mix ng-if and ng-click (and most other directives). To do that, you'll be safer if you always write to atributes of another object instead of a simple variable. It is plain JavaScript prototypal inheritance in play.
<li ... ng-init="category.limitItems = maxItemsPerList">
ng-init cannot be used in the same element of the ng-repeat otherwise
the var initialised will not be available inside the ng-repeat block
True, in the sense that variables are created in the local scope. But again, refer to an object.
I think there is another way to do that, maybe more clean but in this
specific case I can't do a lot.
You don't need to do a lot, it is quite simple to do it right actually.
Some advices:
Use ng-init with care. I know it will tempt us but always try to put logic inside controllers and services;
Avoid assignments inside templates;
Learn how to use controllerAs syntax. It gives you an object to write your models to (the controller), so solves most problems related to scope inheritance;
Do not inject $scope, put your view models inside controllers.
Full code goes like this:
<li ng-repeat="category in maincategories" ng-init="category.limitItems = maxItemsPerList">
{{category.title}}
<ul>
<li ng-repeat="item in category.items | limitTo: category.limitItems "> {{item.title}}
</li>
</ul>
<a ng-if="category.items.length > maxItemsPerList && category.limitItems != category.items.length" ng-click="category.limitItems = category.items.length" href>
<b> Show more </b>
</a>

Angular js sort a list of items based on few conditions

Angular noob here
I have an angular app in this plunkr.
How do i sort the list displayed here using angular such that the course with the flag always stays on the top and the remaining items are sorted alphabetically?
You can use the orderBy.
Change your ngRepeat to this:
<a ng-repeat="prog in programs | orderBy:'academic_program.program_title' | orderBy:'primary_program':true" href="#" ng-click="display.addprogram = false" class="list-group-item">
Here's the modified plunker: http://plnkr.co/edit/PJBvf5MyGe3ggD2uFkKf?p=preview

Categories

Resources