Sort the data in Angular JS by one key, but ensure that results with another key set to 0 remain at the end

Here is an array of objects containing information about various car brands:

$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},
];

I want to display them in my Angular view based on price, with the highest price coming first and those with no stock listed at the end. Is there a simple way to achieve this sorting in Angular? You can check out a working plunker with the example provided. Thank you!

Answer №1

By eliminating the need for a comparator function, we can simply sort by "stock == 0" since the order by strings are angular expressions. This approach is much more straightforward compared to my original solution using a comparator.

`orderBy:['stock==0','-price']`

http://plnkr.co/edit/HUHaHLwCR4rkLvHm6K0v?p=preview

li p {
  font-family:Arial;
  color:black;
}
.noStock p {
  font-family:Arial;
  color:gray;
  font-style:italic;
}
<!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:['stock==0','-price']" ng-class="{'noStock':car.stock==0}">
        <p>{{ car.brand }} ({{ car.price }}) <span ng-if="car.stock==0">Out of Stock</span></p>
      </li>
    </ul>
  </div>


<script type="text/javascript">
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},
    ];
  
 });
 
</script>
</body>
</html>

Answer №2

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.

Answer №3

Using Angular's ng-repeat directive to display a list of cars sorted by price and stock

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Oops! The provided value for the argument "value" is not a valid query constraint. Firestore does not allow the use of "undefined" as a value

I encountered an error while exporting modules from file A and importing them into file B. When running file B, the error related to Firebase Cloud Firestore is displayed. const getMailEvents = (startTime, endTime) => { serverRef = db.collection("Ma ...

Callbacks in Laika tests go untriggered

Meteor.collection.insert() allows for the use of a callback as one of its arguments. To demonstrate, you can start a new Meteor project and execute the following code in the browser's console. my_collection = new Meteor.Collection("myCollection"); my ...

What is the process for incorporating buttons into an Angular mat-table?

I have successfully utilized Angular mat-table to showcase data retrieved from a database: view the image description here <table mat-table [dataSource]="UserDataSourceFilters" class="mat-elevation-z1 mt-5"> <ng-co ...

React - Pagination with page number not functioning correctly

Currently, I am trying to set up pagination for my website. When I visit localhost:3000/profile/, it displays the first 3 elements correctly. The pagination also functions properly when I input a number like 3 for ${page}, taking me to page 3 seamlessly. H ...

Generating small image previews in JavaScript without distorting proportions

I am currently working on a client-side Drag and Drop file upload script as a bookmarklet. To prepare for the upload process, I am utilizing the File API to convert the images into base64 format and showcase them as thumbnails. These are examples of how m ...

Sass is throwing an error message saying 'Module not found' during the compilation process

After installing sass using npm ($npm install sass), I attempted to create a JSON script. Unfortunately, when running it, I encountered an error stating 'Cannot find module'. ...

What could be causing the queuing of multiple Ajax requests in ExtJS?

I am encountering an issue with my grid setup. I have a menu on the left side for each item on the grid, and this menu's items change based on the selection in the grid. When the event selection is triggered, an Ajax.request function is called to hand ...

Display endless data within a set window size

I am looking to create a fixed-size window for displaying text from the component <Message/>. If the text is longer, I want it to be scrollable within the fixed window size. See screenshot below: Screenshot export default function AllMessages(){ ...

The ngRoute feature seems to be malfunctioning and unable to switch views when an <a> tag is clicked

Just starting out with Angular JS and encountering an issue that has me stumped. Would really appreciate some help in resolving it. In my project, I have an index file connected to app.js which utilizes ngRoute. See the code snippet below for reference: ...

execute a function when an image is clicked using jQuery

How can I create an onclick event for the variable imageCatuaba? function setCatuaba(map) { var imageCatuaba = { url: 'images/catuskov.1.png', origin: new google.maps.Point(0, 0), anchor: new google.maps.Point(0, 32) }; I'm ...

Drawing unusual shapes using canvas arcs in Coffeescript

@.ctx.lineWidth = 20 @.ctx.moveTo(i.x, i.y) @.ctx.arc(i.x, i.y, 3, 0, Math.PI * 2) Can you explain how the code snippet above contributes to the image displayed? ...

Ways to deactivate the submit button using Cookies, sessions, or local storage

Although cookies and storage can be deleted, they can still help prevent many human spammers who are unaware of this. How can I temporarily disable the form submit button on a specific page for just one day? I want to create a code that saves "Submitted" ...

Tips for releasing a dual npm package with both CommonJS and module support to ensure consistent imports of submodules

Trying to figure out how to package an NPM package so that it includes both CommonJS and ES modules that can be imported using the same absolute module path has been a challenge for me. I want to ensure that regardless of whether it's in a node or bro ...

The voting system will increase or decrease by 1 to 5 during each round

Recently, I added a voting system to my website inspired by this source. It's functioning well, but there is an issue where each vote can sometimes count for more than one. You can view the source code on the original website and test it out live here ...

What is the best way to add a style to the currently active link on a NavLink component using the mui styled() function

I have a custom NavLink component that I want to style with an ".active" class when it is active. However, I am not sure how to achieve this using the "styled()" function in MUI. Does anyone know how to accomplish this? Below is the code for my custom Nav ...

Flask not serving Favicon and images to a React application

I am currently working with a Flask server and have it set up in the following manner: app = Flask(__name__, static_folder="dist/assets", static_url_path='/assets', template_folder="dist") ...

Having trouble retrieving data from a JSON object that has been stringified. This issue is arising in my project that utilizes Quasar

I successfully converted an excel spreadsheet into a JSON object by using the xml2js parseString() method, followed by JSON.stringify to format the result. After reviewing the data in the console, it appears that I should be able to easily iterate through ...

The latest version of Next.js, 11.1.0, does not support monitoring for code changes within the node

In the latest version of Nextjs (11.1.0), there seems to be an issue where code changes in the `node_modules` directory are not being watched, unlike in the previous version (10.2.1). While working on a project with Nextjs 11.1.0, I have tried explicitly ...

JavaScript Ext is not declared

I've designed a webpage with tabs, and everything was working fine in our development environment. However, when we moved it to the staging environment, we started experiencing errors this morning that I'm not sure how to resolve as my JavaScript ...

Capturing dynamic text from a URL using Protractor and Node.js

How can I extract the 'PR001-CC001234' segment from a URL using Protractor in Node.js? While I am able to retrieve the current URL and save it as a variable, I am seeking assistance in extracting the dynamic text at the end of the URL. http://exa ...