AngularJS order by array of objects with nested values - angularjs

I have an array of objects like this:
$scope.sortableItems =
[
{
name: 'Blue Shirt',
fields: {Price: 20}
},
{
name: 'Pink Shirt',
fields: {Price: 80},
},
{
name: 'Orange Shirt',
fields: {Price: 10},
}
]
I need to make an ng-repeat field that can sort the products based on price from low to high or high to low.
I tried this:
.product(ng-repeat="item in sortableItems | orderBy:fields.Price")
But it had no effect.
Additionally I have another variable $scope.sortFunction which can equal Price: Low-High or Price: High-Low the end result needs to detect the value of $scope.sortFunction and sort based on the value of the string. Not sure how to do that with an ng-repeat

You can create a function that would return price and use that function inside your orderBy
js
$scope.getPrice = function(item){
return item.fields['Price'];
}
html
<div ng-repeat="item in sortableItems | orderBy:getPrice:false">{{item.fields['Price']}}</div>
order by takes a second boolean value that you can use for asc / desc ordering.
Demo

Related

Get max/min of an attribute sorted based on another key

Suppose I have an array of json objects like:
[{ customerId:1, orderId:1-1, orderAmount:100
customerId:2, orderId:2-1, orderAmount: 125
customerId:1, orderId: 1-2, orderAmount: 112
............
}]
And I want to find the highest (or lowest) order per customer like
[{customerId:1, orderId:1-2, orderAmount:112},{.....}]
Is it possible to do either using any language construct (I am using Node.js) or lodash. I think can either sort by customerId or sort by orderAmount is straightforward in lodash but not the above combination
The only other way I can think of is double forEachOf (async) loop which may not be very efficient
Any help is appreciated....
Use orderBy with with order ascending or descending to decide if lowest or highest. Group by custormerId, and take the 1st item from each customer orders:
function getMinMax(orders, min) { // orders - array of orders, min - true if minimum, undefined / false if maximum
var order = !!min ? 'asc' : 'desc';
return _(orders)
.orderBy('orderAmount', order) // orderBy the orderAmount property, with order determining highest or lowest
.groupBy('customerId') // group all orders by customer id
.map(function(orders) { // create a new array of just the 1st order of each customer, which will be the highest or the lowest
return orders[0];
}).value();
}
var orders = [{
customerId: 1,
orderId: '1-1',
orderAmount: 100
}, {
customerId: 2,
orderId: '1-2',
orderAmount: 128
}, {
customerId: 2,
orderId: '1-3',
orderAmount: 12
}, {
customerId: 1,
orderId: '1-3',
orderAmount: 113
}, {
customerId: 2,
orderId: '1-1',
orderAmount: 125
}, {
customerId: 2,
orderId: '4-1',
orderAmount: 11
}, {
customerId: 1,
orderId: '1-2',
orderAmount: 25
}];
var highestOrders = getMinMax(orders);
console.log('highestOrders', highestOrders);
var lowesetOrders = getMinMax(orders, true);
console.log('lowesetOrders', lowesetOrders);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.2/lodash.min.js"></script>
_.sortBy allows you to specify an array of fields to sort with. You can use:
var output = _.sortBy(input, ['customerId', 'orderAmount']);
If you want to also group the objects into arrays so that it is easier to find the max & min for each customerId, you can use _.groupBy and then sort.
var output = _.mapValues(_.groupBy(input, 'customerId'), function(val) {
return _.sortBy(val, 'orderAmount');
});
This would produce a structure like:
{
"1": [
{ customerId: 1, orderId: "1-2", orderAmount: 112 },
{ customerId: 1, orderId: "1-1", orderAmount: 100 }
],
"2": [
{ customerId: 2, orderId: "2-1", orderAmount: 125 }
]
}

Filter unique date values from JSON

I am using unique filter to display JSON data.
This is my JSON data:
data= [
{
itemId: "100",
name: "x001",
date: "2016-01-16T16:17:38.928-05:00"
},
{
itemId: "102",
name: "x002",
date: "2016-01-16T16:05:20.928-05:00"
},
{
itemId: "103",
name: "x003",
date: "2016-01-15T10:10:01.715-05:00"
},
{
itemId: "104",
name: "x004",
date: "2016-01-15T12:15:01.715-05:00"
},
{
itemId: "105",
name: "x005",
date: "2016-01-14T12:15:25.928-05:00"
}
]
I am trying to display itemswith no repeated date, so that my output will be:
x001
x003
x005
How do I use unique filter which filters only date value (not consider Time stamp in date field)
here is my HTML code:
<div ng-repeat="item in result | unique:'date'">
{{name}}
</div>
See if this helps: How to make ng-repeat filter out duplicate results
Basically says:
you must include filters as an additional reference in your module angular.module('yourModule', ['ui', 'ui.filters']);

How to group array of hashes by one key and merge inner keys and arrays

How can I transform an array of hashes:
[{
id: 115,
ref_id: 440000000000337,
properties: [{name: "test"}],
type: "content"
},{
id: 116,
ref_id: 440000000000337,
properties: [{name: "asdf"}],
type: "content"
}]
to get the desired result:
{
id: 440000000000337
type: "content"
properties: [{name: "test"}, {name: "asdf"}]
}
in one block smarter then [sic] in the example? Would it be best to obtain this [sic] results with ruby functions?
in = _
out = {properties: []}
in.map {|i| out[:id] = i[:ref_id]; out[:properties] << i[:properties]; out[:type] = i[:type]}
out[:properties].flatten!
You cannot use the variable name in since it is a keyword. I will use iin instead.
out = {
id: iin.last[:ref_id],
type: iin.last[:type],
properties: iin.flat_map{|e| e[:properties]}
}

How to use ngoptions to generate an optgroup without repeating the group name

Hello i'm trying to use ng-options to get a grouping of countries by region. It only works by repeating the group name in every row. Is it possible to do it using the following json :
$scope.countries = [
{ region: "americas", countries: [{ value: "usa", key: "1" }, { value: "mexico", key: "2" }] },
{ region: "Africa", countries: [{ value: "3", key: "Algeria" }, { value: "4", key: "Morocco" }, { value: "5", key: "Tunisia" }] },
];
ng-options is pretty locked down in it's definition, so you'll probably need to loop through your countries array and add the region, something like:
$scope.countries_with_regions = [];
$scope.countries.forEach(function(region){
region.countries.forEach(function(country){
country.region = region.region;
$scope.countries_with_regions.push( country );
});
});
then you can do your ng-options with the countries_with_regions
You data structure fo countries needs to be like
countries = [{value : 3, key: "algeria", region : "africa"}, ...]
for the ng-options to be able to "group by" region.

OrderBy with enumerable property in AngularJS

I have an object array where every object can have an array of properties, like this
[
{
name: 'Big house',
properties: [{name: 'Area',value: '400'}, {name: 'Year',value: '1950'}]
},
{
name: 'Small house',
properties: [{name: 'Area',value: '400'}, {name: 'Year',value: '1950'}]
},
{
name: 'Green house',
properties: [{name: 'Area',value: '40'}, {name: 'Year',value: '2008'}]
},
{
name: 'Red house',
properties: [{name: 'Area',value: '250'}, {name: 'Year',value: '1999'}]
},
];
Now I'd like to order this list by one of the properties, say Area, using a filter in ng-repeat. Is that possible?
I've been play around with this in plunker (http://plnkr.co/edit/GEgLxv5zJyW0ZBTtJR5S?p=preview) but cannot figure out how to do.
Thanks in advance
This will work if the area is always the first property:
<tr ng-repeat="house in houses | orderBy:'properties[0].value'">
Also make sure that the area is defined as an integer, right now they are strings. So 250 will be sorted before 40.
So remove the quotes from the numbers:
{
name: 'Area',
value: 400
}
, {
name: 'Year',
value: '1950'
}

Resources