When using the orderBy function, a comparator function is required that receives pairs of two objects
{value: '<your element>', type: <string, number, ...>, index: <element position>}
and should return
<-1, 0, 1>
.
You have the option to create a custom comparator that compares stock elements, considering only 0 and >=1, then sorts by price and finally by index.
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.title = "Cars";
$scope.cars = [
{"brand":"McLaren","price":70,"stock":0},
{"brand":"Renault","price":10,"stock":0},
{"brand":"Ferrari","price":100,"stock":3},
{"brand":"Lamborghini","price":50,"stock":2},
{"brand":"Porsche","price":30,"stock":1},
{"brand":"Seat","price":120,"stock":0},
{"brand":"Audi","price":10,"stock":3},
];
$scope.carComparator = function(v1, v2) {
var car1 = v1.value
var car2 = v2.value
var stock1 = car1 && car1.stock > 0
var stock2 = car2 && car2.stock > 0
if (stock1 != stock2) {
return stock2 - stock1;
}
var price1 = car1 && car1.price
var price2 = car2 && car2.price
if (price1 != price2) {
return price2 - price1;
}
return index2 - index1;
}
});
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.min.js"></script>
</head>
<body>
<div ng-controller="myCtrl" ng-app="myApp">
<p>{{title}}</p>
<ul>
<li ng-repeat="car in cars | orderBy:'+': false:carComparator " ng-class="{'noStock': car.stock == 0}">
<p>{{ car.brand }} ({{ car.price }})</p>
</li>
</ul>
</div>
</body>
</html>
The logic behind this comparison function is that stocks are converted into booleans which are used as numbers. Any stock with a value greater than or equal to 1 counts as 1, while any stock less than or equal to 0 counts as 0. If one car is in stock and the other isn't, it returns 1 or -1 to prioritize the first or second car accordingly.
For prices, the larger price takes precedence. If price 1 is higher, a value less than 0 is returned, and if price 2 is higher, a value greater than 0 is returned.
As a last resort, sorting is done based on the original array index to establish a definite order and ensure the sorting process completes.