ng-repeat doesn't work on multidimonsional array - arrays

I have the following array and following code but im stuck. The ng-repeat is not working on this array(for other scopes it works good). I am missing something, but i cant figure out what it is.
Example msgArray (array is created dynamically, i copied this from browser console)
[john: Array[0], Carl: Array[2]]
html Code
<ul>
<li ng-repeat='(k, v) in msgArray'>{{ k }}</li>
</ul>

This is not an array, but an object with array properties. The (k, v) syntax of ng-repeat iterates over each property of the object with k as the key and v as the value. If you want to display the first element of each value, you would do something like:
<li ng-repeat="(k, v) in msgArray">{{ v[0] }}</li>
You can also ng-repeat over v (or "messages" if you want to be more explicit) if you need to do that as well. Note that you only need the (k, v) syntax if you actually want to use the key.
<li ng-repeat="messages in msgArray">
<span ng-repeat="msg in messages">{{msg}}</span>
</li>
http://plnkr.co/edit/jnnvYxVCiHOEnkU4b2Iv?p=preview
Also see the ng-repeat documentation on this

Related

transforming data returned from firebase

What I'm trying to do: receive data from fire base, and display some values from that data to the screen.
How I've gone about doing it: I have created an Angular SPA and the data I return from Firebase is as follows:
Returned Data from Firebase
Error I'm receiving:
I then use an *NgFor loop in the html portion of the component as follows:
<div class="row">
<ul class="list-group" *ngFor = "let guardian of guardians">
<li class="list-group-item">{{ guardian.firstname }}</li>
</ul>
</div>
ERROR Error: Error trying to diff '[object Object]'. Only arrays and iterables are allowed.
I have looked for solutions to this and the common answer is to transform the received data into an array. I have attempted to do that with the following:
for (const guardian in data) {array.push(guardian);}
However, the array I receive back is missing all of my values. It comes back in this form:
["-L3n95t-rxA4-bOgc8fz", "-L3nF0h5EEKtwAiZv0Q7",
"-L3oWoBmoXK3-5XBkx9i", "-L3oWxEhAcUGQX2P4yES", "-L41_cK3KD6DMduhG3P3",
"-L4CbTtNqGuVyT3hzY-R", "-L4CfKsBxfQxSKd2PR4s", "-L4EDFkbsWMrT61fLjhD"]
This allows me to use my *NgFor statement, but this data is useless to me now. Any knowledge on how to transform this data?
After three days of banging my head against this one any help is appreciated! :)
The data in that array is actually each key within the guardians object. Now what you want to do is utilize those keys. Lets assume you gave your key array a value such as this.guardianKeys = array
Then you can iterate through the keys and access the original guardians objects like so:
<div class="row">
<ul class="list-group" *ngFor = "let key of guardianKeys">
<li class="list-group-item">{{ guardians[key].City }}</li>
<li class="list-group-item">{{ guardians[key].Phone }}</li>
<li class="list-group-item">{{ guardians[key].State }}</li>
...
</ul>
</div>
This solution solved my problem.
for (const guardian in data) {array.push(data[guardian]);}
by pushing this into an empty array I was then able to iterate through the array with *NgFor.

Looping in AngularJS not working

I'm trying a simple AngularJS looping using 'ng-repeat' directive as below :
<div ng-app="" ng-init="numbers=[1,3,5,2]">
<ul>
<li ng-repeat="item in numbers">{{ item }}</li>
</ul>
</div>
The result of this is as below, which is perfect
1
3
5
2
However, when I change the 'numbers' array like this
<div ng-app="" ng-init="numbers=[1,3,5,2,2]">
being the rest as is, it does not work.
The only change I have made is that I've added one more item in the 'numbers' array '2'. The issue I figured out is whenever an item is repeated in the array ( '2' in this case ), the problem occurs.
The console log I noticed is like below
Error: [ngRepeat:dupes] http://errors.angularjs.org/1.3.14/ngRepeat/dupes?p0=item%20in%20numbers&p1=number%3A2&p2=2
at Error (native)
at http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js:6:417
at http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js:232:494
at Object.fn (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js:122:53)
at l.$get.l.$digest (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js:123:138)
at l.$get.l.$apply (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js:126:58)
at http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js:17:479
at Object.e [as invoke] (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js:36:315)
at d (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js:17:400)
at tc (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js:18:179)
Also, if the array is of string type values, the same problem persists too.
For example, <div ng-app="" ng-init="names=['Bishnu', 'Sagar', 'John', 'Bishnu']">
in this case also I'm facing the same issue.
This behavior of AngularJS is very strange.
Does anyone know the reason, and how to resolve?
Try this...
The ngRepeat directive instantiates a template once per item from a collection. Each template instance gets its own scope, where the given loop variable is set to the current collection item, and $index is set to the item index or key.
ngRepeat makes the corresponding changes to the DOM
When an item is added, a new instance of the template is added to the DOM.
When an item is removed, its template instance is removed from the DOM.
When items are reordered, their respective templates are reordered in the DOM.
By default, ngRepeat does not allow duplicate items in arrays. This is because when there are duplicates, it is not possible to maintain a one-to-one mapping between collection items and DOM elements.
If you do need to repeat duplicate items, you can substitute the default tracking behavior with your own using the track by expression
<div ng-repeat="n in [42, 42, 43, 43] track by $index">
{{n}}
</div>
Refer:https://docs.angularjs.org/api/ng/directive/ngRepeat
As per the Angular Docs Duplicates are not allowed. You need to use 'track by' expression to specify unique keys.
Created this Plnkr for your reference
<div ng-app="" ng-init="numbers=[1,3,5,2,2]">
<ul>
<li ng-repeat="item in numbers track by $index">{{ item }}</li>
</ul>
</div>
You need to use track by $index to iterate through duplicate entry as well.
you can try like this
<div ng-repeat="value in [4, 4] track by $index">{{value}}</div>

Static list item inside ngRepeat

So,
I am rendering a basic list using ngRepeat, but need the first <li> to be static content, rather than being generated from the data array:
e.g.
<ul ng-repeat="item in items">
<li>This is text from the template and will always be the same.</li>
<li>{{item}}</li>
</ul>
I've also looked at using ng-repeat-start, but just can't quite get to a solution.
It is a common misconception that people want to use ng-repeat on the parent element, when in fact you use it on the actual elements that do the repeating.
You just need to change it to:
<ul>
<li>This is text from the template and will always be the same.</li>
<li ng-repeat="item in items">{{item}}</li>
</ul>

Angular JS - on page load - arranging array in ascending order

Is there a way that I can arrange a simple array like below:
<div ng-init="fruits=['apple','orange','mango','banana','pineapple','kiwi']">
in ascending order on page load
I tried this, but it dint work:
<ul>
<li ng-repeat="fruit in fruits | orderBy:predicate='fruit'">{{fruit}}</li>
</ul>
I'm sure there must be some pretty simple ways but since I'm a novice in Angular, would like help on this.
predicate='fruit' is not a valid orderBy expression (at least not a meaningful one, anyway). To orderBy items in an array as strings, use 'toString()' as the predicate...
<ul>
<li ng-repeat="fruit in fruits | orderBy:'toString()'">{{fruit}}</li>
</ul>
JsFiddle

AngularJS - ng-repeat is not working for inner properties

Here is an object that I'd like to use with ng-repeat, but it's not able to see the inner firstlang property:
$scope.school{
name : "stackoverflow",
sub :{
firstlang : "kannada"
}
}
Here is my ng-repeat:
<ul>
<li ng-repeat="index in school.sub">
first language is = {{index.firstlang}}
</li>
</ul>
The desired result is: first language is = kannada
Looking at your example it is not very clear how the school.sub data structure should look like in the end... Is it supposed to be an object (as in the example data structure) or an array (as you ngRepeat seems to suggest).
Provided that the school.sub is an object this would work: http://jsfiddle.net/pkozlowski_opensource/WXsFD/1/
<li ng-repeat="(key, value) in school.sub">first language is = {{value}}</li>
On the other hand, if you plan your sub structure to be an array the proper approach would be:
http://jsfiddle.net/pkozlowski_opensource/WXsFD/2/
<li ng-repeat="index in school.sub">first language is = {{index.firstlang}}</li>
Hope that the above jsFiddles clarify how to approach both situations.

Resources