I am getting a server response and binding these data to view using ng-repeat. Now I want to sort these data by priceList
and name
. I am able to sort name using orderBy
, but not with priceList
. I want to sort the products based on priceList
. Sorting with name will change the order of list while sorting by priceList
will effect only the order of products
of each category
. It will effect the order of displayed category. Please help me resolve this.
My code:
<div ng-controller="Ctrl">
<pre>Sorting predicate = {{predicate}};</pre>
<hr/>
<table class="friend">
<tr>
<th><a href="" ng-click="predicate = 'name'; reverse=false">Name</a>
</th>
<th><a href="" ng-click="predicate = 'priceList'>price</a></th>
</tr>
</table>
<div ng-repeat="data in _JSON[0].categories | orderBy:predicate">
<div ng-repeat="vals in data.itemTypeResults |orderBy:'partTerminologyName'" id="{{vals.partTerminologyName}}">
`<h4 style="background-color: gray">{{vals.partTerminologyName}} : Position :{{vals.position}}</h4>`<br>
<div ng-repeat="val in vals.products">
<b> Quantity:{{val[0].perCarQty}}</b><br>
<b> part:{{val[0].partNo}}</b><br>
<b>sku:{{val[0].sku}}</b><br>
<b> qtyInStock:{{val[0].qtyInStock}}</b><br>
<b> priceList:{{val[0].priceList}}</b><br>
<b>priceSave:{{val[0].priceSave}}</b><br>
<b> qtyDC:{{val[0].qtyDC}}</b><br>
<b> qtyNetwork:{{val[0].qtyNetwork}}</b><br>
<b> priceCore:{{val[0].priceCore}}</b><br>
</div>
</div>
</div>
JS:
$scope._JSON = [
{"categories":
[
{"id":14061,"name":"Drive Belts",
"itemTypeResults":[
{"partTerminologyName":"Serp. Belt",
"position":"Main Drive",
"products":{
"5060635":[
{"perCarQty":2,"partNo":"5060635",
"sku":"20060904","qtyInStock":2,"qtyNetwork":4,
"qtyDC":6,"priceList":19.15,"priceSave":3.29,
"priceCore":10.0}
],
"635K6":[
{"perCarQty":9,"partNo":"635K6",
"sku":"10062449","qtyInStock":2,"qtyNetwork":4,
"qtyDC":6,"priceList":18.15,"priceSave":3.21,"priceCore":10.0}
]
}
}
]
},
{"id":2610,"name":"Drive Belt Tensioners, Idlers, Pulleys & Components",
"itemTypeResults":[
{"partTerminologyName":"Drive Belt Tensioner Assembly",
"position":"N/A",
"products":{
"950489A":[
{"perCarQty":4,"partNo":"950489A",
"sku":"10150833","qtyInStock":2,"qtyNetwork":4,
"qtyDC":6,"priceList":18.15,"priceSave":3.21,"priceCore":10.0
}
]
}},
{"partTerminologyName":"Drive Belt Idler Pulley","position":"N/A",
"products":{
"89161":[
{"perCarQty":1,"partNo":"89161",
"sku":"99995959","qtyInStock":2,"qtyNetwork":4,
"qtyDC":6,"priceList":17.15,"priceSave":3.21,"priceCore":10.0}
],
"951373A":[
{"perCarQty":2,"partNo":"951373A","pla":"LTN",
"plaName":"Litens",
"sku":"10150926","qtyInStock":2,"qtyNetwork":4,
"qtyDC":6,"priceList":18.15,"priceSave":3.21,"priceCore":10.0}
]
}
}
]
}
]
}
];
$scope.predicate = '';
Fiddle: Fiddle
I am getting a server response and binding these data to view using ng-repeat. Now I want to sort these data by priceList
and name
. I am able to sort name using orderBy
, but not with priceList
. I want to sort the products based on priceList
. Sorting with name will change the order of list while sorting by priceList
will effect only the order of products
of each category
. It will effect the order of displayed category. Please help me resolve this.
My code:
<div ng-controller="Ctrl">
<pre>Sorting predicate = {{predicate}};</pre>
<hr/>
<table class="friend">
<tr>
<th><a href="" ng-click="predicate = 'name'; reverse=false">Name</a>
</th>
<th><a href="" ng-click="predicate = 'priceList'>price</a></th>
</tr>
</table>
<div ng-repeat="data in _JSON[0].categories | orderBy:predicate">
<div ng-repeat="vals in data.itemTypeResults |orderBy:'partTerminologyName'" id="{{vals.partTerminologyName}}">
`<h4 style="background-color: gray">{{vals.partTerminologyName}} : Position :{{vals.position}}</h4>`<br>
<div ng-repeat="val in vals.products">
<b> Quantity:{{val[0].perCarQty}}</b><br>
<b> part:{{val[0].partNo}}</b><br>
<b>sku:{{val[0].sku}}</b><br>
<b> qtyInStock:{{val[0].qtyInStock}}</b><br>
<b> priceList:{{val[0].priceList}}</b><br>
<b>priceSave:{{val[0].priceSave}}</b><br>
<b> qtyDC:{{val[0].qtyDC}}</b><br>
<b> qtyNetwork:{{val[0].qtyNetwork}}</b><br>
<b> priceCore:{{val[0].priceCore}}</b><br>
</div>
</div>
</div>
JS:
$scope._JSON = [
{"categories":
[
{"id":14061,"name":"Drive Belts",
"itemTypeResults":[
{"partTerminologyName":"Serp. Belt",
"position":"Main Drive",
"products":{
"5060635":[
{"perCarQty":2,"partNo":"5060635",
"sku":"20060904","qtyInStock":2,"qtyNetwork":4,
"qtyDC":6,"priceList":19.15,"priceSave":3.29,
"priceCore":10.0}
],
"635K6":[
{"perCarQty":9,"partNo":"635K6",
"sku":"10062449","qtyInStock":2,"qtyNetwork":4,
"qtyDC":6,"priceList":18.15,"priceSave":3.21,"priceCore":10.0}
]
}
}
]
},
{"id":2610,"name":"Drive Belt Tensioners, Idlers, Pulleys & Components",
"itemTypeResults":[
{"partTerminologyName":"Drive Belt Tensioner Assembly",
"position":"N/A",
"products":{
"950489A":[
{"perCarQty":4,"partNo":"950489A",
"sku":"10150833","qtyInStock":2,"qtyNetwork":4,
"qtyDC":6,"priceList":18.15,"priceSave":3.21,"priceCore":10.0
}
]
}},
{"partTerminologyName":"Drive Belt Idler Pulley","position":"N/A",
"products":{
"89161":[
{"perCarQty":1,"partNo":"89161",
"sku":"99995959","qtyInStock":2,"qtyNetwork":4,
"qtyDC":6,"priceList":17.15,"priceSave":3.21,"priceCore":10.0}
],
"951373A":[
{"perCarQty":2,"partNo":"951373A","pla":"LTN",
"plaName":"Litens",
"sku":"10150926","qtyInStock":2,"qtyNetwork":4,
"qtyDC":6,"priceList":18.15,"priceSave":3.21,"priceCore":10.0}
]
}
}
]
}
]
}
];
$scope.predicate = '';
Fiddle: Fiddle
Share Improve this question edited Dec 27, 2015 at 19:04 Ved asked Dec 22, 2015 at 17:56 VedVed 12.1k5 gold badges45 silver badges61 bronze badges 12-
4
$filter('orderBy')(vals.products, "priceList" )
ought to work – Korgrue Commented Dec 22, 2015 at 18:05 - Can you update my fiddle. It will be helpful a lot for me. – Ved Commented Dec 22, 2015 at 18:07
-
priceList
is not an attribute of any category. According to your JSON, Every category has multiple products, and each product is an array of elements each of which has a priceList. How exactly do you want to order the categories by priceList? – abl Commented Dec 22, 2015 at 18:10 -
2
@Ved I've seen the fiddle, and I repeat what I said. In your code, you are trying to order the categories by priceList:
ng-repeat="data in _JSON[0].categories | orderBy:predicate"
andng-click="predicate = 'priceList'
. Every category has multiple products. The price belongs to the product, not the category. How do you want to order the categories by price, when categories have no price? Perhaps you want to order the products by price, inside each category? – abl Commented Dec 22, 2015 at 18:58 - 1 @Ved are you stuck to this particular JSON format? The first thing I would do is see if I could return the format in a way the front end can work with more easily. If that is not an option, I would reorganize the data in a (Angular) service so that it is easier to display it using Angular. – Daan van Hulst Commented Dec 24, 2015 at 13:50
4 Answers
Reset to default 2 +50You might need to define a very good sorter function, or sort your products
before they are interpreted by ng-repeat
. I've created sorter function using underscore.js (or lodash).
You can checkout the demo (or the updated demo). Products are first sorted by category and then sorted by price in every category.
<!-- in html -->
<button ng-click="sortFn=sortByPrice">Sort By Price</button>
<button ng-click="sortFn=doNotSort">Do not Sort</button>
...
<div ng-repeat="val in sortFn(vals.products)">
...
// in js
$scope.sortByPrice = function(products) {
return _.sortBy(products, function(product) {
return product.length > 0 ? product[0].priceList : 0;
});
};
$scope.doNotSort = function(products) {
return products;
};
$scope.sortFn = $scope.doNotSort; // do not sort by default
BTW: You are directly calling val[0]
, which is very dangerous, if the product does not contain any elements, your code will break. My code won't ;-)
Update 1
The author asks me for a more pure Angular way solution.
Here is my answer: I think my solution is exactly in Angular way. Usually you can implement a filter (similar to orderBy
) which wraps my sortByPrice
. Why I don't do that, because you have ng-click
to switch your order filter. I'd rather put control logic into a controller, not as pieces into view. This will be harder to maintain, when your project keeps growing.
Update 2
Okay, to make the +50
worthy, here is the filter version you want, (typed with my brain piler) Please check in fiddle
You need to organize the products in other estructure. For example:
$.each($scope._JSON[0].categories , function( i , e) {
$.each(e.itemTypeResults, function(sub_i,sub_e) {
$.each(sub_e.products, function(itemTypeResults_i,product) {
console.log(product);
var aProduct = new Object();
aProduct.priceList = product[0].priceList;
aProduct.name = e.name;
$scope.products.push(aProduct);
});
} )
});
The code is not very friendly but what i do is putt all the products in one array so they can be ordered by the price. You have the products inside categories so that's why angular is ordering by the price in each category.
Fiddle: http://jsfiddle/7rL8fof6/1/
Hope it helps.
Your fiddle updated: http://jsfiddle/k5fkocby/2/
Basically: 1. Digested the plex json object into a flat list of objects:
var productsToShow = [];
for (var i=0; i < json[0].categories.length; i++){
var category = json[0].categories[i];
for (var j=0; j<category.itemTypeResults.length;j++){
var item = category.itemTypeResults[j];
var products = item.products;
for (var productIndex in products) {
var productItems = products[productIndex];
for (var k=0; k<productItems.length;k++){
var productItem = productItems[k];
// Additions:
productItem.categoryName = category.name;
productItem.partTerminologyName = item.partTerminologyName;
productItem.position = item.position;
productsToShow.push(productItem);
}
}
}
}
Show category title only when needed by:
ng-repeat="product in (sortedProducts = (productsToShow | orderBy:predicate))"
and
ng-show="sortedProducts[$index - 1].partTerminologyName != product.partTerminologyName"
you can sort from your database and get final JSON data..
db.categories.aggregate([{$group : {category : {your condition} }, price: {$sort : { price: 1 } },}}])