$index restart each row in ng-repeat - arrays

I want to repeat this code for each element in my array:
<div class="container" ng-init="parentIndex = $index" ng-repeat="urn in apsocket.mensajes | filter:searchTextURN">
<button style="width:100%" type="button" class="btn btn-info" data-toggle="collapse" data-target="{{'#urn_'+$index}}">{{urn.urn }}</button>
<div id="{{'urn_'+$index}}" class="collapse">
{{urn.timestamp}}
<br>
<p>
<div align="right" ng-repeat="meas in urn.measurements track by $index">
<button style="width:90%;background-color: #68ec6a;border-color:#8bf48c;" type="button" class="btn btn-success" data-toggle="collapse" data-target="{{'#meas_'+parentIndex + '_' +$index}}">{{meas.phenomenon}} </button>
<div style="width:90%" id="{{'meas_'+parentIndex + '_' +$index}}" class="collapse">
{{meas.value + ' ' + meas.uom}}
</div>
</div>
</p>
</div>
</div>
But, while first button in each row works fine and creates a working collapsible, the inner ng-repeats seem not.
Each inner element in each outter row, have the same id. So, for each "container", parentIndex is the same and starts in 0.
What should I do in this case? This is not a fixed array which I load at the beggining. This array recevies data from socket and it get bigger each time a message is received.
If you need any more code or so, just ask.

I would recommend just using the pure angular way. In a repeat, each item has it's own scope so you can do an ng-click="collapse = ! collapse" (something like that), I made you an example here
http://jsfiddle.net/X8era/82/
I just made a fake data structure for examples sake
<ul>
<li ng-repeat="item in objs" ng-click="collapse = ! collapse">
{{item.id}}
<ul ng-show="item.more.length > 0 && collapse">
<li ng-repeat="child in item.more" ng-click="collapse = ! collapse; $event.stopPropagation();" >
{{child.id}}
<ul ng-show="child.more.length > 0 && collapse">
<li ng-repeat="baby in child.more">
{{baby.id}}
</li>
</ul>
</li>
</ul>
</li>
</ul>
If you would like to use the collapse class for an animation or whatever, you can change the part of the ng-show that is collapse to
ng-class="{ 'collapse' : collapse }"
The first 'collapse' being whatever class you want to be toggled.

You don't have to use ng-init="parentIndex = $index". You can access to parent $index like this $parent.$index.
Each ng-repeat creates new scope, that's why you can access to parent by using $parent keyword.
Demo:
var app = angular.module('app',[]);
app.controller('ctrl', function($scope) {
$scope.items = [0, 1, 2, 3, 4];
});
<div ng-app="app" ng-controller="ctrl">
<ul>
<li ng-repeat="item in items track by $index">
<ul>
<li ng-repeat="item in items track by $index">
parent: {{$parent.$index}}
current: {{$index}}
</li>
</ul>
</li>
</ul>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

Related

ngRepeat Add to the current index

I have the following code, I want to add 1 to the current index of the second Name, because if I don't, it will output the same name in a single line. How do I add to the current index of ngRepeat?
<ul id="speakerlist" ng-repeat="data in result">
<li>
<div class="col">
<h3>{{data.Name}}</h3>
</div >
<div class="col">
<h3>{{data.Name | $index+1}}</h3>
</div>
</li>
</ul>
I solved this by using jQuery, but I want to do it in angularjs way.
EDIT: additional info
var app=angular.module("myApp",[])
app.controller("myController",function($scope){
$scope.result=[{"Name":"Michael Jordan"},{"Name":"Kobe Bryant"},{"Name":"Kevin Durant"},{"Name":"Stephen Curry"} ];
});
The result I want Is:
Michael Jordan Kobe Bryant
Kevin Durant Stephen Curry
If I understand correctly, you want to display a li for every two items. You can do it something like this:
<ul id="speakerlist" ng-repeat="data in result">
<li ng-if="$even">
<div class="col">
<h3>{{result[$index].Name}}</h3>
</div >
<div class="col">
<h3>{{result[$index + 1].Name}}</h3>
</div>
</li>
</ul>
Of course you would also have to include some kind of check if the $index can reach the last one (if the collection has an un-even amount of items)
See this jsfiddle
You could even remove the double col html if you don't like duplicate html code:
<ul id="speakerlist" ng-repeat="data in result">
<li ng-if="$even">
<div class="col"
ng-repeat="item in [result[$index], result[$index + 1]]">
<h3>{{item.Name}}</h3>
</div >
</li>
</ul>
Try this code <h3>{{data.Name }} {{$index+1}}</h3> instead of your code
<h3>{{data.Name | $index+1}}</h3>
The result format looks like
Ramesh
Ramesh1
Rajendran
Rajendran1
I think you can make it simple this way.
var app=angular.module("myApp",[])
app.controller("myController",function($scope){
$scope.result=[{"Name":"hari"},{"Name":"ram"} ];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp" ng-controller="myController">
<ul id="speakerlist" ng-repeat="data in result track by $index">
<li>
<div class="col">
<h3 >{{data.Name}} {{data.Name+1 }}</h3>
</div >
</li>
</ul>
</body>
">
Why don't you do this ?
<ul id="speakerlist" >
<li ng-repeat="data in result">
<div class="col">
<h3>{{data.Name}}</h3>
</div >
</li>
</ul>
This way you don't need to change de $index, it will be automatic

Updating Repeat Items Index

I have a collection of items which I am displaying in my view using ng-repeat. I also have two buttons, one to move the item to the left, and the other to move the item to the right.
View
<div data-ng-repeat="item in items">
<!--Move Item Index to the Left-->
<a href="#">
<i ng-click="move($index, $index - 1)" class="fa fa-chevron-left"></i>
</a>
<!--Move Item Index to the Right-->
<a href="#" >
<i ng-click="move($index, $index + 1)" class="fa fa-chevron-right"></i>
</a>
<h1>{{item.name}}</h1>
</div>
Controller
$scope.move = function(fromIndex, toIndex) {
var element = $scope.items[fromIndex];
$scope.items.splice(fromIndex, 1);
$scope.items.splice(toIndex, 0, element);
};
The array is updating but the changes are not reflected in the UI.
How can I get the changes to reflect in the UI?
It is working correctly. Just add some text in the i tag and click on it.
<div data-ng-repeat="item in items">
<!--Move Item Index to the Left-->
<a href="#">
<i ng-click="move($index, $index - 1)" class="fa fa-chevron-left">Left</i>
</a>
<!--Move Item Index to the Right-->
<a href="#" >
<i ng-click="move($index, $index + 1)" class="fa fa-chevron-right">Right</i>
</a>
<h1>{{item}}</h1>
</div>
It is just working, see JSFiddle
(I removed the css classes because no css lib available in the example)
index.html
<div id="app" ng-controller="MainCtrl">
<div data-ng-repeat="item in items">
{{item}}
<!--Move Item Index to the Left-->
<
<!--Move Item Index to the Right-->
>
</div>
</div>
app.js
angular.module('myApp', [])
.controller('MainCtrl', function ($scope) {
$scope.items = ['a', 'b', 'c'];
$scope.move = function (fromIndex, toIndex) {
var element = $scope.items[fromIndex];
$scope.items.splice(fromIndex, 1);
$scope.items.splice(toIndex, 0, element);
};
});
angular.bootstrap(document.querySelector('#app'), ['myApp']);
Note that you cannot move the first item back and the last item forward, because the first item already is the first of the list :).
Don't forget to add some text (for screenreaders!) to the chevrons and it's better to set the ng-click on the anchors.
href="#" is not necessary. You don't want to link to # (which usually is the landing page of your app) -> <a href ng-click="...">
Even better: if you want the have a pointer cursor, you could use CSS for this: cursor: pointer and omit the href.
Well, I created this example on Plnkr and it is changing position
I just moved MOVE method to <a> tag.
<!doctype html>
<html ng-app>
<head>
<script src=".../angular.min.js"></script>
<script src="script.js"></script>
</head>
<body>
<div ng-controller="Ctrl">
<div data-ng-repeat="item in items">
<!--Move Item Index to the Left-->
<a href="#" ng-click="move($index, $index - 1)">
<i class="fa fa-chevron-left"></i>
Left
</a>
<!--Move Item Index to the Right-->
<a href="#" ng-click="move($index, $index + 1)" >
<i class="fa fa-chevron-right"></i>
Right
</a>
<h1>{{item.name}}</h1>
</div>
</div>
</body>
</html>
function Ctrl($scope) {
$scope.items = [{name:'aa'}, {name:'bb'}, {name:'cc'},{name:'dd'}]
console.log($scope.items)
$scope.move = function(fromIndex, toIndex) {
console.log($scope.items)
var element = $scope.items[fromIndex];
$scope.items.splice(fromIndex, 1);
$scope.items.splice(toIndex, 0, element);
};
}

I'm having issues with ng-click when using it within an accordion w/ ng-repeat

Still new to AngularJS and am working on adding some bootstrap elements. I'm working on using an accordion to provide categories (and eventually sub-categories) that will filter a set of results.
I will likely move this out into a custom filter (once I learn more about that), but trying to get this to work in the mean time.
UPDATE: I'm thinking it may have to do with the scope and needing parent access. Any help here?
<tbody>
<tr ng-repeat="product in products | filter:categoryFilter | filter:query | limitTo: 20 | orderBy: 'Name'" >
<td>{{product.Number}}</td>
<td>{{product.Name}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div id="sidebar">
<div id="box4">
<div>
<h2>Rental Categories</h2>
<accordion close-others="oneAtATime">
<accordion-group heading="All Equipment" is-open="status.isFirstOpen" is-disabled="status.isFirstDisabled">
<li>All Equipment</li>
</accordion-group>
<-- NOT WORKING - EVEN WITH VALUE TYPED OUT -->
<accordion-group ng-repeat="group in groups">
<accordion-heading>
{{group.title}}
</accordion-heading>
<li ng-click="categoryFilter={Category: 'Concrete'}" ng-repeat="contents in group.content">
{{contents.name}}
</li>
</accordion-group>
<-- PASSING VALUE STILL NOT WORKING -->
<accordion-group heading="{{group.title}}" ng-repeat="group in groups" ng-click="categoryFilter={Category: '{{group.title}};}">
<li ng-click="categoryFilter={Category:'{{group.title}}'}" ng-repeat="contents in group.content">
{{contents.name}}
</li>
</accordion-group>
</accordion>
</div>
<-- THIS WORKS - BUT IT IS NOT ACCORDION STYLE OR WITH A REPEAT FOR CATEGORIES -->
<div class="content">
<ul class="style2">
<li class = "first" ng-click="panel.selectTab(1); categoryFilter=''" ng-class="{ active:panel.isSelected(1) }">
All Equipment
</li>
<li ng-click="categoryFilter={Category: 'Concrete'}">
Concrete & Masonry
</li>
<li ng-click="panel.selectTab(2); categoryFilter={Category: 'Concrete'}" ng-class="{ active:panel.isSelected(2) }">
Concrete & Masonry
</li>
<li ng-click="panel.selectTab(3); categoryFilter={Category: 'Drills & Hammers'}" ng-class="{ active:panel.isSelected(3) }">
Drills & Hammers
</li>
My groups are referenced in a controller as follows:
$scope.groups = [
{
title: 'Concrete',
content: [
{id:1, name:'Grinders'},
{id:2, name:'Polishers'},
{id:3, name:'Tools'}
]
},
{
title: 'Drills & Hammers',
content: [
{id:1, name:'Dynamic Group Body - 1'}
]
},
{
title: 'Floor Mainentance',
content: [
{id:1, name:'Dynamic Group Body - 1'}
]
}];
I've made sure my group.title matches my product.Category. Any advice on why this filter is not being passed within this structure, would be greatly appreciated.
It might be helpful to include a jsfiddle or plunker with your code so we can see what you're actually trying out. From what I gathered, I created this jsfiddle.
<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true" ng-controller="myController">
<div class="panel panel-default" ng-repeat="group in groups">
<div class="panel-heading" role="tab" id="heading_{{$index}}">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapse_{{$index}}" aria-expanded="false" aria-controls="collapse_{{$index}}">
{{group.title}}
</a>
</h4>
</div>
<div id="collapse_{{$index}}" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading_{{$index}}">
<div class="panel-body">
<ul>
<li ng-repeat="content in group.content">{{content.name}}</li>
</ul>
</div>
</div>
</div>
If that isn't what you're trying to accomplish, please elaborate a bit on what you are trying to accomplish and provide more code. Thanks.

how to select a li which is nested within another ng-repeat in angular js

(please do not update the english grammer in this question/ I wont be able to approve it and this question wont get resolved.)
This is my UI
It contains various li elements whose values are populated using this angular html
<div class="row">
<li class="no-bullet-li li-12 monaco-font"> {{selectedChangeEligibilityPlan}}</li>
<ul class="ul-plan-1">
<li class="no-bullet-li" ng-repeat="plan in fewThings">
<div ng-class="{ 'selected-class-name': $index == selectedIndex }" ng-click="itemClicked($index)" class="li-alt monaco-font"> p2|{{plan.planName}} | {{plan.planId}}
<a class="iconing-sub" ng-click="addClick(item)" href=""><i class="glyphicon glyphicon-plus"></i></a>
<a ng-click="deleteClick(item)" ng-class="{ active : active.one }" href=""><i class="glyphicon glyphicon-remove iconing_1-sub"></i></a>
</div>
<ul class="ul-plan">
<li class="no-bullet-li li-8 monaco" ng-repeat="item in plan.planIds">
p1| {{ plan.planNames[$index]}} | {{item}}
<a <a ng-click="editClick(item)" href=""><i class="glyphicon glyphicon-pencil iconing"></i></a>
<a ng-click="deleteClick(item)" href=""><i class="glyphicon glyphicon-remove iconing_1"></i></a>
</li>
</ul>
</li>
</ul>
</div>
It uses the nested ng-repeat.
The whole UI is contained within a one controller ( no directives used)
the following code gets triggered when someone clicks the blue lis.
$scope.itemClicked = function ($index) {
console.log($index);
// console.log($(item).closest('li') );
$scope.selectedIndex = $index;
};
here's how to ui looks and its great.
problem arises when I try to do the same logic for the pink ones (nested ng-repeat li). It selects other pink lis in all the other stack too.
here's the screenshot.
second part of question:
I have I have the above UI plus I also have this second UI that is loaded along with this on the same page. It contains a bunch of horizontal rows.
Once the user click the blue pink colored lis it goes into the active state. Then the user can click the row which he likes. upon clicking it the plan name of currently selected li will get replaced.
Here is the html for it.
<div class="row">
<li class="no-bullet-li li-12 monaco-font"> {{selectedChangeEligibilityPlan}}</li>
<ul class="ul-plan-1">
<li class="no-bullet-li" ng-repeat="plan in fewThings">
<div class="li-alt monaco-font"> p2|{{plan.planName}} | {{plan.planId}}
<a class="iconing-sub" ng-click="addClick(item)" href=""><i class="glyphicon glyphicon-plus"></i></a>
<a ng-click="deleteClick(item)" ng-class="{ active : active.one }" href=""><i class="glyphicon glyphicon-remove iconing_1-sub"></i></a>
</div>
<ul class="ul-plan">
<li ng-class="{ 'selected-class-name': $index == selectedIndex }" ng-click="itemClicked($index)" class="no-bullet-li li-8 monaco" ng-repeat="item in plan.planIds">
p1| {{ plan.planNames[$index]}} | {{item}}
<a ng-click="editClick(item)" href=""><i class="glyphicon glyphicon-pencil iconing"></i></a>
<a ng-click="deleteClick(item)" href=""><i class="glyphicon glyphicon-remove iconing_1"></i></a>
</li>
</ul>
</li>
</ul>
</div>
The problem lies in the fact that you are trying to save the state of the data (which one is selected) inside your controller using $index. The $index property isn't unique among different ng-repeats, so when you set your $scope.selectedIndex to $index, each of your sub lists will see that their $index matches, and so will each trigger the ng-class and add the selected-class-name class.
What you could do instead is have each item in the data have a unique index and use that id to store which item is selected in $scope.selectedIndex.
<ul class="ul-plan">
<li ng-class="{ 'selected-class-name': item.id == selectedIndex }" ng-click="itemClicked(item.id)" class="no-bullet-li li-8 monaco" ng-repeat="item in plan.planIds">
p1| {{ plan.planNames[$index]}} | {{item}}
<a ng-click="editClick(item)" href=""><i class="glyphicon glyphicon-pencil iconing"></i></a>
<a ng-click="deleteClick(item)" href=""><i class="glyphicon glyphicon-remove iconing_1"></i></a>
</li>
</ul>
This line looks strange.
<a ng-click="select('one')" href="">
Did you really mean to pass a hardcoded 'one' to the function? Or was it supposed to be the index, like the deleteClick() call.

Angular ng-repeat element count

<li ng-repeat="Item in Items">
<div ng-switch="($index)==0">
<div ng-switch-when="true">
< Previous
</div>
<div ng-switch-when="false">
{{$index}}
</div>
</div>
</li>
I want to get element count of the Items and want to show "Next >" for last item
Something like this
<li ng-repeat="Item in Items">
<a ng-if="$first" href="#">< Previous</a>
<a ng-if="!$first && !$last" href="#">{{$index}}</a>
<a ng-if="$last" href="#">Next ></a>
</li>
To get the length use Items.length. It becomes more complex if there is a filter. See this SO post

Resources