How to use $index in ng-repeat angular js - javascript

I have posted my question
How to create check box from multidimensional array using angular js
But I have not gotten any response. I have debug my code when I am going to add second ng-repeat I am getting
Error: ngRepeat:dupes Duplicate Key in Repeater
When I am adding repeat by $index I am getting single character as key and value too
Please help me I am new in angular js :(
This is my fiddle of code http://jsfiddle.net/ashishoft/03L3faq5/2/

Here is example:
ng-repeat="i in items track by $index"

Pretty simple really. You can even use it in combination with custom directives etc. Its basically an index of where you are in the loop.
There are some flaws with using it though. If your creating an ng-repeat list, and then passing the $index into some click function or something, then you can have issues if your also using filtering on that same list. The $index can fall out of sync with the filters and leave you wondering why its giving you wrong data.
for example:
<li ng-repeat="page in links | someFilter:filter">
<a ng-click="someFunction($index)">{{ someData }}</a>
</li>
vs the better way of:
<li ng-repeat="itemX in someData | someFilter:filter">
<a ng-click="someFunction(itemX)">{{ itemX.name }}</a>
</li>
So although I use the $index in my example below, its often best just to pass the whole object in when doing more complex functions per row.
HTML:
<div ng-app="myApp" ng-controller="MainCtrl">
<ul>
<li ng-repeat="page in links">
<a ng-class="{ testClass: $index == pageNumber }" ng-click="setPageNumber($index)">{{ page }}</a>
</li>
</ul>
</div>
Javascript:
var app = angular.module('myApp', []);
app.controller('MainCtrl', function($scope) {
$scope.links = [
'Link One',
'Link Two',
'Link Three'
];
$scope.pageNumber = 0;
$scope.setPageNumber = function(index) {
$scope.pageNumber = index;
}
});
CSS:
.testClass {
background: black;
color: white;
}

This is a sample of how it could be written, although using $index is just fine. Might I suggest using something else like the element id or title, here is an article that talks about ng-repeat.
<div class="favorite-children" ng-repeat="photo in ctrl.favorties track by $index">
<div class="card"></div>
</div>
//or
<div class="favorite-children" ng-repeat="photo in ctrl.favorties track by photo.title">
<div class="card"></div>
</div>
Update
Try this FIDDLE for a preview of a comprehensive JSON, with your same code previewed on how you can use it. Hope it helps.

Related

How to reset the value of $index in ng-repeat nested loops?

I have this code and not sure is it right or wrong the way to implement it. But definitely so far not working in my view.
<div ng-repeat="data in DataObject">
<ul style="list-style-type:decimal !important;">
<li ng-repeat="(indexX,answer) in bkm.content_detail.question_data.question_content[0].question_answer[0].answer_text track by $index">
{{indexX+1}} - {{answer | joinBy : " / "}}
</li>
<div ng-init="indexX=0"></div>
</ul>
</div>
Well, I tried to make value of indexX=0 at ng-init="indexX=0". Is it true the way I've done it?
The purpose I need to reset the value of indexX is because of nested loop of ng-repeat at the outer div.
You can add a directive to your ng-repeat loop that can utilize the scope.$last parameter to reset your index on the last element.
Example:
https://stackoverflow.com/a/13472605/6452040

ng-show not working properly on initial page load

So I was working on a webpage using html, css and Angular.js and I wanted to display the page based on what the user has selected on the dropdown list. The "filter" when the user selects his/her choice works perfectly but initially when the page is loaded I could not get the entire page content to be displayed, instead it displays a blank page.
This is a snippet of my code:
<select ng-model="selectedOption" ng-options="data.id as data.name for data in myData.categories"></select>
<div class="main" >
<ul id="cbp-ntaccordion" class="cbp-ntaccordion" ng-repeat="data in myData.profiles" ng-show="selectedOption == data.category" >
<li class="cbp-ntopen">
<h3 class="cbp-nttrigger">{{data.name}}</h3>
<div class="cbp-ntcontent">
I'm getting an error like:
angular.js:13708Error: [ngRepeat:dupes] errors.angularjs.org/1.5.7/ngRepeat/dupes?
You may use ng-value="defalutvalue" so your code is something like that
<select ng-model="selectedOption" ng-value="defalutvalue" ng-options="data.id as data.name for data in myData.categories"></select>
<div class="main" >
<ul id="cbp-ntaccordion" class="cbp-ntaccordion" ng-repeat="data in myData.profiles" ng-show="selectedOption == data.category" >
<li class="cbp-ntopen">
<h3 class="cbp-nttrigger">{{data.name}}</h3>
<div class="cbp-ntcontent">
From the error that you mentioned, I think you are not giving Angular a way to figure out how to note your object as unique. Use a track by expression in your ng-repeat.
So your ng-repeat would become: ng-repeat="data in myData.profiles track by $index"
See the Tracking and Duplicates section of ngRepeat documentation.
<ul id="cbp-ntaccordion" class="cbp-ntaccordion" ng-repeat="data in myData.profiles track by $index" ng-show="selectedOption == data.category">

bind click event to the element in ng-repeat angular

I have menu and use ng-repeat for loop to the my category and in this loop i have a link tag and I want to when clicked on this link do something in js file.
But I can't access to the tag a in javascript and add click event to this element.
Here is my ng-repeat code:
<li class="has-children" ng-repeat="category in categories |filter:{ level: 1 } : true" ng-if="$index < 5">
<a class="parent-link">{{category.categoryName}}</a>
<ul class="is-hidden">
<li class="go-back"><a>{{category.categoryName}}</a></li>
<li ng-repeat="submenu in categories |filter:{ parentID: category.categoryID } : true"><a>{{submenu.categoryName}}</a></li>
</ul>
</li>
Here is my js file (this code doesn't fire):
$(".parent-link").on("click", function(e) {
console.log("clicked");
e.prenvetDefault()
});
Use ng-click. It can be used as attribute of element. Example usage:
HTML:
<div ng-click="changeWord()">
{{word}}
</div>
Controller:
$scope.changeWord = function () {
$scope.word = 'I am changed';
}
See http://jsfiddle.net/ax6k3z1e/
Possible reason could be that you Javascript is getting executed before the DOM is ready. You should use ng-click as It's good to build through Angular way when you are using AngularJS in you application.
ng-Repeat have the tendency to bind your iterating object as well. Below is the example for the same.
<div ng-repeat='ele in elements'>
<p ng-click='ShowAlert(ele)'>{{ele.name}}</p>
</div>
Specify below mentioned code in your linked controller.
$scope.ShowAlert=function(element){
alert(element.Name);
}

Get clicked object value with AngularJS

I'm trying to rewrite a live search feature using AngularJS, but can't find how I can grab the currently clicked item in the list. See below:
<div id="searchResults" ng-show="speaker.list.length > 0">
<ul ng-repeat="person in speaker.list">
<li ng-click="speaker.updateFields()">{{person.name}}</li>
</ul>
</div>
In my speaker.updateFields() method, how do I reference person.name? Is there a different way this should be done?
Thanks.
Pass it in!
<li ng-click="speaker.updateFields(person.name)">{{person.name}}</li>
And the JS
$scope.updateField = function(name) {
//console.log(name)
}
When you use ng-repeat each item is assigned an index value as well.
<div ng-repeat='person in persons'>
{{person.$index}}
</div>

Angular.js Search Query if search form is out of current file

I had this code on index.html:
<div class="container-fluid people-container">
<div class="search">
<!--Sidebar content-->
<span class="search-text">Search:</span>
<input ng-model="query" class="search-input">
<span class="sort-text">Sort:</span>
<select ng-model="orderProp" class="sort-select">
<option value="name">Alphabetical</option>
<option value="age">Date</option>
</select>
</div>
<div class="people-listing">
<!--Body content-->
<ul class="people">
<li ng-repeat="person in people | filter:query | orderBy:orderProp" class="thumbnail person-listing clearfix">
<a class="clearfix" href="#/people/{{person.id}}">
<img class="thumb" ng-src="{{person.imageUrl}}">
<div class="person-info">
<h1 class="title">{{person.name}}</h1>
<span class="year">{{person.born}} - {{person.died}}</span>
</div>
</a>
</li>
</ul>
</div>
</div>
I decided to divide the UI into partials, and moved the search part to search.html:
<div class="search">
<!--Sidebar content-->
<span class="search-text">Kërko:</span>
<input ng-model="query" class="search-input">
<span class="sort-text">Radhit sipas:</span>
<select ng-model="orderProp" class="sort-select">
<option value="name">Alfabetit</option>
<option value="age">Vitit</option>
</select>
</div>
Before doing this, the search form was working great. After I moved it to another template, it doesn't work. I have no idea because this is my first day working with Angular.js, and I'd need some help. Also, here's what on my controllers.js:
var deshmoretControllers = angular.module('deshmoretControllers', []);
deshmoretControllers.controller('PeopleListCtrl', ['$scope', 'Person',
function($scope, Person) {
$scope.people = Person.query();
$scope.orderProp = 'age';
}]);
...
Plunker:
http://plnkr.co/edit/J98O34dBFaUchhKdT6ck
i fixed the code.. there were lots of issues in it.. WORKING PLUNKER LINK
1. you need ng-controller which covers both search & results, you kept the controller on just each box & not on list
2. make sure that you ng-model never uses value without dot, rather than query - use variable as search.query
2b. make sure to initialize the search object in controller $scope.mysearch = {};
I did below modification
moved controller to list.html rather than search.html
init $scope.mysearch = {} in controller
We this is a prototypal inheritance problem.
Assuming you are moving the template and referencing it with ng-include. ng-include creates a new scope.
You set your query in the new scope, not in the parent scope that is part of PeopleListCtrl
To fix it define the query as object on the parent scope
$scope.query={term:''}
Then reference this as query in partial search.html
<input ng-model="query.term" class="search-input">
In this way the child scope can manipulate the object properties defined on parent.
As long as the parent child relationship is there you can now access the update query data in the parent scope.
Also the declaration of ng-controller=PeopleListCtrl should be on the parent element of where the search.html is inserted if used. If the controller is injected using $route definition then nothing needs to change.
Since the query has changed to object all reference should be to now query.term like
ng-repeat="person in people | filter:query.term | orderBy:orderProp"
To know more about prototypal inheritance and scopes see this wiki https://github.com/angular/angular.js/wiki/Understanding-Scopes

Categories