I'm in trouble with a foreach that I need to do with Angular.
Thats's what I want to do :
<ul>
<div ng-repeat="g in groups">
<li ng-repeat="c in g.commands">{{c.text}}</li>
<li class="divider"></li>
</div>
</ul>
How can I do something like that, but in valid HTML structure ? (without a <div> between <ul> and <li>)
I see only one solution :
Replace the <div> with a <ul> and make a lot of css rules to make it like it doesn't exists
In addition, I use Angular 1.4.8.
Thanks !
You shouldn't have to alter your data structure at all. Instead just utilize the ng-repeat-start & ng-repeat-end directive. You'll have separate <ul>s but in terms of rendering, you can easily modify the CSS to make it appear to be a seamless list.
<ul ng-repeat-start="g in groups">
<li ng-repeat="c in g.commands">{{c.text}}</li>
<li ng-repeat-end class="divider"></li>
</ul>
http://codepen.io/jusopi/pen/KVZBLv
Probably the easiest way is to use a custom collection groupedCommands that is bound to the angular scope in code and contains the items in the correct order.
Then use ng-repeat-start for the enhanced repeat directive. There is a special ng-repeat-start and ng-repeat-end attribute combination that you can use for this case:
<ul>
<li ng-repeat-start="c in groupedCommands">{{c.text}}</li>
<li class="divider" ng-repeat-end></li>
</ul>
Try This one,
<ul>
<!-- ng-repeat: g in groups -->
<span ng-repeat="g in groups">
<li ng-repeat="c in g.commands">{{c.text}}</li>
<li class="divider"></li>
</span>
</ul>
This may solve your problem.
Caution : It is not a good way to use <span> between <ul> and <li>.
Related
<ol ng-repeat="item in ctrl.items">
<h3 ng-bind-html="item.title"></h3>
<li ng-repeat="description in item.items" ng-bind-html="description"> </li>
</ol>
This is how it is rendered on screen:
**Title1**
1. Desciption1
2. Description2
**Title2**
1. Description1
But as per the HTML standards, ol should only contain li, not h3.
Any idea how we can achieve this?
Why don't you just wrap this construction in one more block? Placing h3 tag in this case will be correct enough.
<div ng-repeat="item in ctrl.items">
<h3 ng-bind-html="item.title"></h3>
<ol>
<li ng-repeat="description in item.items" ng-bind-html="description"></li>
</ol>
</div>
In other case, if you would like to create list of lists and you really want to use <ol> for both you can do in the next way:
<ol ng-repeat="item in ctrl.items">
<li>
<h3 ng-bind-html="item.title"></h3>
<ol>
<li ng-repeat="description in item.items" ng-bind-html="description"></li>
</ol>
</li>
</ol>
In this way you have nested lists, but all h3 tags are inside the li tag, not inside the oldirectly. That is fine. HTML syntax rules allow headings tags in the li elements. I would prefer to use first variant, because it looks clearer and more understandable.
But second one also is a valid HTML structure according to W3 validator:
Use div inside li tag
as follows:
<li ng-repeat="description in item.items">
<div>
<h3 ng-bind-html="item.title"></h3>
<div ng-bind-html="description"></div>
</div></li>
I was using ng-click inside the nested ng-repeat but found that the inner most ng-click(3rd level) was not getting triggered.
But when I used track by $index for the inner most ng-repeat, ng-click got triggered.
I am not able to understand this behavior of nested ng-repeat.
Please find below the code snippet
<ul class="a">
<li class="b" ng-repeat="items in Objects track by $index" ng-click="callSomething()">
<a>{{items.name}}</a>
<ul class="c">
<li class="d" ng-repeat="items1 in Objects1 track by $index" ng-click="callSomething()">
<a>{{items1.name}}</a>
<ul class="e">
<li class="f" ng-repeat="items2 in Objects3 track by $index" ng-click="callSomething()">
<a>{{items3.name}}</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
Its really related to ng-repeat behavior. Each element is tracked uniquely and mapped to the scope. I think this thread already answers your questions:
How does ng-repeat work?
I have a weird question regarding the no-show
I have something like
<ul>
<li ng-repeat="item in items" >
<a ng-click="showNew =! showNew">{{item.text}}
<span ng-show="showNew">New Items!</span>
</a>
</li>
<li ng-show="showNew">
<a >Category 1 </a>
</li>
</ul>
For some reason, only the 'New Items!' was shown when I click a tag. The Category 1 would never show. I thought showNew would be in the same scope for everything in my case. How do I solve this? Thanks a lot!
You can use ng-init to create the variable higher up in the template and that should help. This is not an ideal fix but it is quick and easy if you don't want to edit other files.
EDIT: you will need to use dot notation in your model so the angular scope magic can work. (this is the equivolent of $scope.nested = {showNew: false}
<ul ng-app ng-init="nested.showNew=false">
<li ng-repeat="item in [1,2,3]" >
<a ng-click="nested.showNew =! nested.showNew">{{$index}}
<span ng-show="nested.showNew">New Items!</span>
</a>
</li>
<li ng-show="nested.showNew">
<a >Category 1 </a>
</li>
</ul>
http://jsfiddle.net/0692dbak/
I need to create a html structure as follows:
<ul>
<li id="r1_1">Root node 1
<ul>
<li id="child_node_1">Child node 1</li>
<li id="child_node_2">Child node 2</li>
<li id="child_node_3">Child node 3</li>
</ul>
</li>
<li id="r1_4">Root node 2
<ul>
<li id="child_node_4">Child node 4</li>
<li id="child_node_5">Child node 5</li>
</ul></li>
</ul> </div>
My issue is that i am unable to generate the id indexes. i need to do
this using angularjs. can someone please help? I am very new to angularjs.
As tymeJV mentioned, you can use ng-repeat and $index to do it.
Here is a working plunker with an example:
http://plnkr.co/edit/S4H08rHgpQlGhY18VkNP?p=preview
<ul>
<li ng-repeat="root in rootNodes" id="someprefix_{{calculateRootId($index)}}">
{{root.node}} calculated id: someprefix_{{calculateRootId($index)}}
<ul>
<li ng-repeat="item in root.items" id="someprefix_{{$index +1}}">Child node {{$index + 1}}</li>
</ul>
</li>
</ul>
Edit: updated plunkr to meet your requirement, note that the use of a helper function to calculate the id is very useful, BUT it would be nice to give your array items (roots and childs) an Id variable that is previously calculated on your controller and simply bind to it.
The above solution works, but I would not recommend it. I like to separate the logic from the view as much as I can, and it is a best practice to do it. Having said that, check out this other example: http://plnkr.co/edit/QsnZFlCx347nnSnkFj7W?p=preview
Here the logic of the id generation is all in the controller, so the view can bind directly to the calculated ids, and that also make it easier to change or customize even further that logic if necessary:
<ul>
<li ng-repeat="root in rootNodes" id="{{root.id}}">
{{root.name}} id: {{root.id}}
<ul>
<li ng-repeat="item in root.items" id="item.id">{{item.name}} id: {{item.id}}</li>
</ul>
</li>
</ul>
Hope that helps.
I would like to do this really basic example :
<div ng-controller="ctrl">
<li ng-repeat="config in configs">
<span >Config : {{config}}</span>
<li ng-repeat="version in versions">
{{config}}
</li>
</li>
</div>
So basically, I got 2 imbricated ng-repeat loop, and I would like to access a value of the first loop from the second one.
I thought it was really basic, but no way to make it work. My result of that is 1 liwith the config printed, and 3 empty sub lis
I already tried a lot of combination list {{$parent.index}}, {{$parent.config}} etc ...
I'm pretty sure this has to do with the structure of your HTML.
Here is a working plunker.
Since you are omitting the <ul> tags that are required for lists. The nested <li> is causing a display issue.
I have simple wrapped the <li> with <ul> and it seems to work fine:
<div ng-controller="ctrl">
<ul>
<li ng-repeat="config in configs">
<span >Config : {{ config }}</span>
<ul>
<li ng-repeat="version in versions">
VersionConfig: {{ config }}
</li>
</ul>
</li>
</ul>
</div>