Loop through an array of objects with ng-repeat angular - arrays

I can't find a way to loop through my array of json objects with angular .
My array looks like that in firebug(Each series of objects have an index value.):
[[0], Object { idliste=0, id=1, photo="pot.jpg", plus...}, Object { idliste=0, id=3, photo="pot.jpg", plus...}]
[[1], Object { idliste=1, id=1, photo="pot.jpg", plus...}, Object { idliste=1, id=3, photo="pot.jpg", plus...}]
[[2], Object { idliste=2, id=1, photo="pot.jpg", plus...}, Object { idliste=2, id=3, photo="pot.jpg", plus...}]
It has been produced by this code :
var idListe = $scope.getIdListe();
$scope.listeCommandes[idListe]= new Array([idListe]);
for (i=0;i<$scope.panier.length;i++){
$scope.listeCommandes[idListe].push({
idliste:idListe,
id: $scope.panier[i].id,
photo: $scope.panier[i].photo,
nom: $scope.panier[i].nom,
quantite:$scope.panier[i].quantite,
prix: $scope.panier[i].prix,
heureajout:$scope.getHeure()
});
};
$scope.getIdListe = function(){
var idListe = $scope.listeCommandes.length;
return idListe;
};
And the html is :
<div ng-repeat="idliste in listeCommandes" >
<div ng-repeat="(nom, id) in idliste">
{{nom}} : {{id}}
</div>
</div>
It doesn't work. I really can't figure how to make it work, it means, simply print each objects, following the index number.
THank you if u got any idea. I've searched the forums but can't find any solution. Maybe it's the way i 've created an index that is wrong ?

finally answered my problem by adding an angular module called angular-filter "mentionned within this example:
http://jsbin.com/weyov/45/edit?html,js,output
Thank a lot for you help .
Now my code look like that :
var idListe = $scope.getIdListe();
for (i=0;i<$scope.panier.length;i++){
$scope.listeCommandes.push({
idliste:idListe,
id: $scope.panier[i].id,
photo: $scope.panier[i].photo,
nom: $scope.panier[i].nom,
quantite:$scope.panier[i].quantite,
prix: $scope.panier[i].prix,
heureajout:$scope.getHeure()
});
};
and the html :
<ul ng-repeat="(key, value) in listeCommandes | groupBy: 'idliste'">
Group name: {{ key }}
<li ng-repeat="article in value">
article: {{ article.nom}}
</li>
</ul>
then my orders are now all automtically grouped by ID in the html view :
Group name: 0
article: Pots Gris
article: Pot Vert
Group name: 2
article: Pot Bleu
article: Pot Vert
article: Pinceaux
Group name: 5
article: Pots Gris
article: Pot Vert
article: Pot Rouge
article: Pot Bleu

Related

AngularJS ng-repeat and indexOf() to check objects

I have two json objects (data1 and data2) that have related information. Namely, both objects have properties (arrays) which in turn can have identical data. So, I am trying to figure out how to display those data with highlighting them properly, i.e. identical data with green color and non-identical with red color. Somehow it wrongly highlights all data with red color.
Here is the html:
<ul>
<li ng-repeat="item in vm.data2.features"
ng-class="vm.data1.features.indexOf(item) !== -1 ? 'check' : 'uncheck'">
<span ng-bind="item.id"></span>
</li>
</ul>
and objects:
vm.data1 = {
id: '4569',
name: 'Given data',
features: [
{id: "TEST_TEXT2", desc: 'smth12'},
{id: "TEST_PPP", desc: 'smthsmthsmth'},
{id: "TEST_ECASH", desc: "somelongtexthere"}
]
};
vm.data2 = {
id: '1305',
name: 'Base data',
features: [
{id: "TEST_BP", desc: 'smth'},
{id: "TEST_TEXT2", desc: 'smth12'},
{id: "TEST_PPP", desc: 'smthsmthsmth'},
{id: "TEST_TEXT1", desc: 'blahblah'},
{id: "TEST_ECASH", desc: "somelongtexthere"}
]
};
The full demo is here.
Any help would be appreciated.
Indexof() method will look for similarity in object references not the id itself. findIndex() method can help you here instead.
vm.hasFeature = function(item){
var hasElements= vm.data1.features.findIndex(function(e){
return e.id == item.id;
});
console.log(item, hasElements);
return hasElements;
}
And in html
<li ng-repeat="item in vm.data2.features"
ng-class="vm.hasFeature(item) > -1 ? 'check' : 'uncheck'">
vm.hasFeature = function(item){
var hasElements= vm.data1.features.findIndex(function(e){
return e.id == item.id;
});
console.log(item, hasElements);
return hasElements;
}
CodePen Link: https://codepen.io/anon/pen/ewgLBN?editors=1010
None of the objects will be the same because indexOf(item) will compare object references of item. You'll need to do a deep equals comparison of the items.
i.e.
{id: "TEST_TEXT2", desc: 'smth12'} === {id: "TEST_TEXT2", desc: 'smth12'} // false
vm.data1.features[0] === vm.data1.features[1] // false
Example using lodash would be something like:
_.some(vm.data1.features, otherItem => _.isEqual(item, otherItem))
Because
_.isEqual(vm.data1.features[0], vm.data2.features[1]) // true
Docs for Lodash:
_.some
_.isEqual

How to collect sub arrays are new Arrays using `computed` method?

I have a list of arrays which contains sub arrays. how to collect those arrays and return them as new array?
here is my attempt but it does not work:
transactions: Ember.computed.map('model.cardList', function(card, index ){
return card.get('transactions');
},[]), // collecting all sub arrays but not works!!
sortedCards: Ember.computed(function(){
return this.get('model.cardList'); //length 4
}.property([])), //can i store here?
What is the correct way to collect the sub arrays from parent arrays? It is required for sorting purpose.
Thanks in advance.
Trying here, but nothing works:
Twiddle
Update
According to the twiddle, I would like to print the categoryName with fruit name(s) as a list.
If your solution at the end demands working with arrays of arrays and keeping them sorted, look at the following solution.
I have added a new field called origin to your model so that we have another field to sort by:
model(){
return {
"values" : [
{
"category" : "categoryD",
"origin": "Kongo",
"fruits" :[{"name":"banana"},{"name":"gova"}]
},
{
"category" : "categoryA",
"origin": "Italy",
"fruits" :[{"name":"apple"},{"name":"orange"}]
},
{
"category" : "categoryC",
"origin": "Marocco",
"fruits" :[{"name":"pineapple"}]
},
{
"category" : "categoryB",
"origin": "Brasil",
"fruits" :[{"name":"mongo"}]
}
]
}
}
And this is how your controller may look if you want to keep the sorting field dynamic:
import Ember from 'ember';
export default Ember.Controller.extend({
shouldSortByCategory: true,
values: Ember.computed.reads('model.values'),
valuesSortingDynamic: Ember.computed('shouldSortByCategory', function(){
return (Ember.get(this, 'shouldSortByCategory') ? ['category:asc'] : ['origin:asc'])
}),
valuesSortedDynamically: Ember.computed.sort('values', 'valuesSortingDynamic'),
actions: {
changeSortField(){
this.toggleProperty('shouldSortByCategory');
},
},
});
I do not care about sorting direction now (asc vs desc), but the field by which we sort is dynamic: category vs origin and is distinguished by the shouldSortByCategory flag.
The template looks pretty much the same:
<ul>
{{#each valuesSortedDynamically as |value|}}
<li>
{{#if shouldSortByCategory}}
<strong>{{value.category}}</strong> - {{value.origin}}
{{else}}
<strong>{{value.origin}}</strong> - {{value.category}}
{{/if}}
<ul>
{{#each value.fruits as |fruit|}}
<li>{{fruit.name}}</li>
{{/each}}
</ul>
</li>
{{/each}}
</ul>
Adjusted twiddle is to be found here: twiddle with dynamic sorting.
UPDATE
Cumulating all fruits into a single array preserving info about the category they belong to can be achieved as follows:
arrayOfFruitsArray: Ember.computed('model.values.[]', function(){
const values = this.get('model.values');
const cumulatedfruits = Ember.A();
values.forEach((value)=>{
const category = Ember.get(value, 'category');
const fruits = Ember.get(value, 'fruits');
fruits.forEach((fruit)=>{
fruit.category = category;
cumulatedfruits.pushObject(fruit);
})
});
return cumulatedfruits;
})
Updated twiddle.
In your case you don't even have to compute sub-arrays of array.
Given the model that you load as follows (taken from your twiddle):
export default Ember.Route.extend({
model(){
return {
"values" : [
{
"category" : "category1",
"fruits" :[{"name":"banana"},{"name":"gova"}]
},
{
"category" : "category2",
"fruits" :[{"name":"apple"},{"name":"orange"}]
},
{
"category" : "category3",
"fruits" :[{"name":"pineapple"}]
},
{
"category" : "category4",
"fruits" :[{"name":"mongo"}]
}
]
}
}
});
It's enough that you iterate over your arrays in the template:
<ul>
{{#each model.values as |value|}}
<li>
{{value.category}}
<ul>
{{#each value.fruits as |fruit|}}
<li>{{fruit.name}}</li>
{{/each}}
</ul>
</li>
{{/each}}
</ul>
Here is the respective Gist. Note that the only file I touched is the template.

How-To: groupBy in an ng-repeat to get count of items in group

I have a list pulled from C#. I'll call it Teams. Teams has a few properties: Team Type, and Team Members (which is a subset list).
[
{
"team": {
"teamName": "The First Team",
"teamType": 1
}
},
{
"team": {
"teamName": "The Second Team",
"teamType": 2
}
},
{
"team": {
"teamName": "The Third Team",
"teamType": 2
}
}
]
My goal:
I'd like to have an ng-repeat where it I show the team type, and how many teams of that type there are, kind of like so:
<div>
<li ng-repeat="team in teams | groupBy: teamType>
Type: {{::teamType}} -- Count: {{::numberOfTeamsOfType}}
</li>
</div>
and it might look like this:
Type: 1 -- Count: 1
Type: 2 -- Count: 2
Using the angular-filter module var myApp = angular.module("myApp", ['angular.filter']); and given the object array structure you have provided, you can do this:
<li ng-repeat="(key, value) in teams | groupBy: 'team.teamType'">
Team Type: {{value[0].team.teamType}} -- Count: {{value.length}}
</li>
jsfiddle here

AngularJS toArray converts object keys to numbers

I use angular-filter in my project to sort the output objects by page the problem is when I use syntax like this:
<ul class="catalog-list"
ng-repeat="(key, value) in list | groupBy: 'styl' | toArray | orderBy:'page'">
{{key}}
<li ng-repeat="dziecko in value | filter:search | bookmark:search"
ng-class="{active:isActiveTab(dziecko)}"
ng-click="openItem(dziecko)">
{{dziecko.rodzina}}
<b>{{dziecko.page}}</b>
</li>
</ul>
Angular converts 'styl' properties ['nowoczesny','klasyczny'..] to numbers. Sorting works fine but I want to obtain names instead of numbers.
groupBy return an object, and orderBy expect array as an argument, so that's the reason you should use toArray filter.
toArray work like that:
Usage: object | toArray: addKey[optional]
if addKey set to true, the filter also attaches a new property $key to the value containing the original key that was used in the object we are iterating over to reference the property
So, you can do something like this example, or take a look on the jsbin
JS:
$scope.groups = [
{ category: 'alpha', id: 2 },
{ category: 'beta', id: 3 },
{ category: 'gamma', id: 0 },
{ category: 'alpha', id: 4 },
{ category: 'beta', id: 5 },
{ category: 'gamma', id: 1 }
];
HTML:
<ul ng-repeat="group in groups | groupBy:'category' | toArray:true | orderBy:min">
<!-- print the group name -->
<li>{{ group.$key }}</li>
<!-- iterate over the group members and order each group by id -->
<li ng-repeat="item in group | orderBy:'id'">
{{ item }}
</li>
</ul>
RESULT:
alpha
{"category":"alpha","id":2}
{"category":"alpha","id":4}
beta
{"category":"beta","id":3}
{"category":"beta","id":5}
gamma
{"category":"gamma","id":0}
{"category":"gamma","id":1}
An array has no named keys. It has integers as position. So don't use toArray.

Filter in ng-options not working

I have an object that maps IDs to their objects. I would like to display the list of these object and use a filter, but I cannot get it to work. Specifically, I'm trying to prevent object with ID 2 from appearing in the options Here's what I've got:
http://jsfiddle.net/9d2Za/
<div ng-app ng-controller="ctrl">
Unfiltered:
<select ng-model="selectedBidType"
ng-options="bidType.id as bidType.label for (bidTypeID, bidType) in bidTypes">
</select>
<br>
Filtered:
<select ng-model="selectedBidType"
ng-options="bidType.id as bidType.label for (bidTypeID, bidType) in bidTypes | filter:{id: '!2'}">
</select>
</div>
Please note: I cannot change the structure of the bidTypes object in whatever fix we come up with. Here's my AngularJS:
function ctrl($scope)
{
$scope.selectedBidType = 1;
// Bid type objects are indexed by ID for fast lookup (this cannot be changed in solution)
$scope.bidTypes = {
1: {id: 1, label: "Buy"},
2: {id: 2, label: "Sell"},
3: {id: 3, label: "Missing"}
};
}
As described by the documentation, the filter filter only accepts an array as first parameter, not an object. In such cases, I personally use a custom filter to make the transformation:
myModule.filter(
'objectToArray',
[
function ()
{
return function (object)
{
var array = [];
angular.forEach(object, function (element)
{
array.push(element);
});
return array;
};
}
]
)
;
And then, in the template:
<select ng-options="… in bidTypes | objectToArray | filter:{id:'!2'}">

Resources