how i get total of item in ng-repeat - angularjs

I'm trying to get the overall number of items in each iteration.my code is this
<ul class="phones">
<li ng-repeat="phone in phones | filter:query | orderBy:orderProp"
ng-init="index()" class="thumbnail">
<a href="#/phones/{{phone.id}}" class="thumb">
<img ng-src="{{phone.imageUrl}}">
</a>
{{phone.name}}
<p>{{phone.snippet}}</p>
</li>
</ul>
<div>
{{ total }}
</div>
Controller
phonecatApp.controller('PhoneListCtrl', function($scope, $http)
{
$scope.total =0;
$scope.index =function()
{
$scope.total ++;
}
}

By dynamic you mean total no of phones currently displayed after filter is applied.
<ul class="phones">
<li ng-repeat="phone in filtered = (phones | filter:query | orderBy:orderProp)"
ng-init="index()" class="thumbnail">
<a href="#/phones/{{phone.id}}" class="thumb">
<img ng-src="{{phone.imageUrl}}">
</a>
{{phone.name}}
<p>{{phone.snippet}}</p>
</li>
</ul>
<div>
{{ filtered.length }}
</div>
To make more sense of data (Bonus Tip :) )
<div ng-show="query">
<ng-pluralize count="filtered.length" when="{'0': ' No search result ', 'one': ' 1 search result ', 'other': ' {} search results '}"></ng-pluralize> for {{query}}
</div>

Are you trying to get total number of phones?
you can simply use length property in expression instead {{ total }}
{{ phones.length }}

Related

Why does $parent.$index equals $index?

In AngularJS 1.6.3 it is basically possible to nest ng-repeat.
I have determined, that in two nested ng-repeat the $parent.$index equals $index.
The following code is given:
<div ng-repeat="category in :: $ctrl.categories">
<span id="category-{{ $index }}">
{{ :: category.name }}
</span>
<ul>
<li ng-repeat="data in :: category.links"
id="link-{{ $parent.$index }}-{{ $index }}">
{{ :: data.name }}
</li>
</ul>
</div>
Expected resulting ID's for LI:
<div>
<span id="category-0">CatA</span>
<ul>
<li id="link-0-0">[..]</li>
<li id="link-0-1">[..]</li>
<li id="link-0-2">[..]</li>
</ul>
</div>
<div>
<span id="category-1">CatB</span>
<ul>
<li id="link-1-0">[..]</li>
<li id="link-1-1">[..]</li>
</ul>
</div>
Actual resulting ID's for LI:
<div>
<span id="category-0">CatA</span>
<ul>
<li id="link-0-0">[..]</li>
<li id="link-1-1">[..]</li>
<li id="link-2-2">[..]</li>
</ul>
</div>
<div>
<span id="category-1">CatB</span>
<ul>
<li id="link-0-0">[..]</li>
<li id="link-1-1">[..]</li>
</ul>
</div>
Can someone confirm this behaviour? Or did I miss something?
Working as expected.
angular.module('test', []).controller('Test', Test);
function Test($scope) {
var $ctrl = this;
$ctrl.categories = [
{
name: 'cat1',
links: [{name: 'l1'}, {name: 'l2'}, {name: 'l3'}]
},
{
name: 'cat2',
links: [{name: 'l4'}, {name: 'l5'}]
}
]
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.3/angular.min.js"></script>
<div ng-app='test' ng-controller='Test as $ctrl'>
<div ng-repeat="category in :: $ctrl.categories">
<span id="category-{{ $index }}">
{{ :: category.name }}
</span>
<ul>
<li ng-repeat="data in :: category.links"
id="link-{{ $parent.$index }}-{{ $index }}">
{{ :: data.name }}
</li>
</ul>
</div>
</div>
You probably have some scope generating elements surrounding your child layer e.g. ng-if, ng-repeat, ng-switch. In this case you'll need to add more layers of $parent

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

AngularJS: Hide li element when it's clicked

I have a html code:
<div class="col-xs-6">
<ul class="list-group itemList">
<li class="list-group-item" ng-repeat="(id, product) in drinks" ng-click="addToShoppingList(id)">
<strong>{{ product.name }}</strong> - {{ product.price | currency }}
</li>
</ul>
</div>
And the Angular code:
$scope.addToShoppingList = function(id){
};
I just want the id element to disappear (hide, fadeOut etc), when it's clicked. I bet it's something about the ng-hide but for now I'm too dumby for that.
Thanks for any answers.
Edit: It should be inside the addToShoppingList function.
Edit2: This is the whole function:
$scope.addToShoppingList = function(id){
$scope.itemsToBuy.push($scope.drinks[id]);
};
When the li element is clicked, it pushes that element to the new array. And then it should be hidden.
Edit3: If I want to cancel it and make the items come back to the array, the result is strange.
You could do something like this:
<div ng-controller="MyCtrl2">
<h2>Hide each LI:</h2>
<ul>
<li ng-click="pushItem(suggestion)" ng-repeat="suggestion in results" ng-click="visible = false">
{{suggestion}}
</li>
</ul>
</div>
Below is the angular code:
var myApp = angular.module('myApp',[]);
function MyCtrl2($scope) {
$scope.results = [1, 2, 3, 4];
$scope.itemsToBuy = [];
$scope.pushItem = function(item){
$scope.itemsToBuy.push(item);
$scope.results.splice($scope.results.indexOf(item),1);
}
}
JS Fiddle on the same:
http://jsfiddle.net/59gdo817/
On the vice-versa, just add the item back to results array to show the li back.
You can add a new status to the $scope.drinks array called isHidden which will track whether or not the item is hidden. When the user clicks on that li, the function will set isHidden to true and the ng-hide will immediately cause it to hide from the DOM.
<div class="col-xs-6">
<ul class="list-group itemList">
<li class="list-group-item" ng-repeat="(id, product) in drinks" ng-click="addToShoppingList(id)" ng-hide="product.isHidden===true">
<strong>{{ product.name }}</strong> - {{ product.price | currency }}
</li>
</ul>
</div>
$scope.addToShoppingList = function(id){
$scope.itemsToBuy.push($scope.drinks[id]);
$scope.drinks[id].isHidden = true;
};
How about this:
<div class="col-xs-6">
<ul class="list-group itemList">
<li class="list-group-item" ng-repeat="(id, product) in drinks" ng-click="addToShoppingList(id);" ng-hide='product.hidden'>
<strong>{{ product.name }}</strong> - {{ product.price | currency }}
</li>
</ul>
</div>
And in your addToShoppingList, you can set the product to hidden:
$scope.addToShoppingList = function(id){
$scope.itemsToBuy.push($scope.drinks[id]);
$scope.drinks[id].hidden = true;
};

$index restart each row in ng-repeat

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>

Infinite loop Error: [$rootScope:infdig]

I created a function delay(), to get random delay number for animation, everything is working fine, but in console I get this infinite loop Error: [$rootScope:infdig]. I'd like to set delay() iteration number = work record number, how can I do it ?
HTML:
<div id="work" class="work" ng-controller="WorkCtrl">
<ul class="grid">
<li class="wow zoomIn" data-wow-delay="0.{{ delay() }}s" ng-repeat="w in work | orderBy:'id':true">
<a href="{{ w.link }}" target="blank_">
<div class="background"></div>
<h3 class="name">{{ w.name }}</h3>
<p class="description">{{ w.description }}</p>
<img ng-src="{{ w.image_path }}">
</a>
</li>
</ul>
JS:
var app = angular.module("portfolio", []);
app.controller('WorkCtrl', function($scope, $http) {
$http.get('work.json').success(function(work) {
$scope.work = work;
});
$scope.delay = function(minNum, maxNum) {
minNum = 0;
maxNum = 5;
return (Math.floor(Math.random()*(maxNum - minNum + 1)) + minNum);
};
});
Thank You Blazemonger, I wrote a new array with an extra attribute delay, now it works like a charm with no errors.
HTML:
<div id="work" class="work" ng-controller="WorkCtrl">
<ul class="grid">
<li class="wow zoomIn" data-wow-delay="0.{{ w.delay() }}s" ng-repeat="w in workList | orderBy:'item.id':true">
<a href="{{ w.item.link }}" target="blank_">
<div class="background"></div>
<h3 class="name">{{ w.item.name }}</h3>
<p class="description">{{ w.item.description }}</p>
<img ng-src="{{ w.item.image_path }}">
</a>
</li>
</ul>
</div>
JS:
$scope.workList = [];
angular.forEach($scope.work, function(item) {
minNum = 0;
maxNum = 5;
$scope.workList.push({
item: item,
delay: (Math.floor(Math.random()*(maxNum - minNum + 1)) + minNum)
});
});

Resources