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

Vue.js does not have the ability to toggle a font-awesome icon

I am having trouble toggling a font awesome icon based on a boolean value. It seems that the font-awesome icon stays on the screen even after it is drawn: Check out this link for reference HTML: <script src="https://unpkg.com/vue"></script> ...

What is the best way to combine the elements within an array with the elements outside of the array in order to calculate their sum?

The goal is to create a function that determines the winner using two input integers. The function should return the first input if it is greater than the second input. function determineWinner(a, b) { let result = [] for (let i = 0; i < 3; i++) ...

Unable to retrieve input using jquery selector

I am attempting to detect the click event on a checkbox. The Xpath for the element provided by firebug is as follows, starting with a table tag in my JSP (i.e. the table is within a div). /html/body/div[1]/div/div/div[2]/div/div[2]/div[1]/div/div[2]/table ...

Exploring html select and input elements in a loop

Currently, I am in the process of developing an application that calculates the total price of selected items based on user input. Each row consists of two dropdown menus (ID/item) and a quantity input field. Additionally, users have the option to add rows ...

tips for patiently awaiting an ajax response before setting the object

I am currently working on a basic todo app using React. Initially, everything was running smoothly when I stored my data in a pre-defined object. However, now that I am retrieving my data from a link (rest) using AJAX, I seem to be encountering some issues ...

Tips for uploading images in Next.js using Firebase

While following a tutorial on Next.js, I encountered an issue with the outdated version of Firebase being used. Despite trying different solutions from the documentation and various sources, I am still facing an error message while attempting to upload ima ...

Efficient methods to reach the desired result using Selenium WebDriver promises

After working on a piece of code that utilizes Selenium WebDriver to retrieve the text of an element, I am wondering if there is a more concise way to accomplish this task? async function getText(driver, locator) { return await (await driver.findEleme ...

Determining the caret position within a textarea using AngularJS

I find myself questioning whether I am on the right track. The issue at hand is my desire to maintain the caret position after updating the textarea value in AngularJS. Here's what the HTML code looks like: <div ng-controlle="editorController"> ...

When I try to run Parcel, my ReactJS website just won't deploy in a serverless environment

For a while now, I've been working on a website using serverless. Everything was going smoothly until this morning when I encountered an issue with pushing updates from my site to the serverless platform. When trying to push, I received the following ...

Select box failing to display default value

I am dealing with a specific data structure: $scope.personalityFields.traveller_type = [ {"id":1,"value":"Rude", "color":"red"}, {"id":2,"value":"Cordial", "color":"yellow"}, {"id":3,"value":"Very Friendly", "color":"green"}, ]; Also, there is a se ...

Navigating data within a JSON file with D3 javascript: a step-by-step guide

Currently, I am attempting to extract and manipulate data from a JSON file using D3 Javascript. Below is the content of the JSON file: { "Resources": [ { "subject": "Node 1", "group" : "1" }, { "predicate": ...

What are the steps to effectively utilize my search bar alongside Google Custom Search?

Here is the HTML code for my form: <form action="#" class="searh-holder"> <input name="se" id="se" type="text" class="search" placeholder="Search.." value="" /> <button class="search-submit" id="submit_btn"><i class="fa fa-sea ...

Exploring how to retrieve the input value from an element with ReactJs

Is there a way to determine if an input field contains a value by referencing another element? Here is my approach: <div className='input-item'> <input ref="accessKey" name="username" className="lci-text" type="text"/> & ...

What could be causing the data to be cut off to zero in my controller?

Currently in the process of migrating an application, and I've encountered some code that was already functioning properly. I have an Angular function that generates random AVL input to test my API. $scope.createAvl = function () { console.log($ ...

HTML5 failing to load button

<!DOCTYPE html> <html> <head> <title>Greetings Earthlings</title> <script src="HelloWorld.js" /> </head> <body> <button onclick ="pressButton()" >Press Me!</button> ...

return to the original secured page based on the most recent language preference

I'm facing an issue with a logical redirection that needs to redirect users to the previous protected page after login. The login functionality is implemented using my custom login page and Google Credentials. Additionally, I have set up a multilingu ...

Transfer a csv file from a static webpage to an S3 bucket

Looking to create a webpage for uploading csv files to an S3 bucket? I recently followed a tutorial on the AWS website that might be helpful. Check it out here. I made some modifications to accept filename parameters in my method, and everything seems to ...

Error Encountered in jQuery UI SelectMenu

Struggling to integrate the jQuery UI SelectMenu, I keep encountering the same error in the browser console. Below is the HTML Code: <select name="files" id="files"> <optgroup label="Scripts"> <option value="jquery">jQuery.js</ ...

Emulate the selection process using element-ui and vue-test-utils

During my unit tests using Jest and Element-ui in Vue, I encountered an issue with a component containing a select element with 2 options. After selecting an option from the dropdown, I needed to verify that a specific action was called. 1) Everything wor ...

Showing and hiding nested Form Group validation in Angular 4 is a crucial feature that can improve

I have been exploring Angular 4 validation recently. Currently, I am working with a reactive form that contains two radio buttons and two form groups. The behavior I'm trying to achieve is when the user selects the first radio button, it removes valid ...