1

Hi I've got an option dropdown list with a list of fruit in alphabetical order with some that out of stock. What i'm trying to achieve is moving the out of stock options in the dropdown to the bottom of the list so the in stock items are displayed above those that are out of stock.

My idea was to find any option that has Out of stock in it then add a class called outOfStock and move this to the bottom of the list. To try and do this I've created a data value for each product using its innerHTML & search for the value "Out of stock" but this only seems to work if i have the full data value in the query. Is there a way that i can find all of the data values that has "Out of stock"? Or is there a different solution that you would suggest that i could achieve moving the out of stock items to the bottom of the options list? Any help would be appreciated

for (const element of document.querySelectorAll(".form-dropdown option")) {
  element.dataset.product = element.innerHTML;
}

document.querySelector(".form-dropdown option[data-product='Cherry - Out of stock']").classList.add('outOfStock');
<select class="form-dropdown">
<option disabled="" value="">Choose option</option>
<option value="0">Apple</option>
<option value="1">Banana</option>
<option value="2">Cherry - Out of stock</option>
<option value="3">Kiwi</option>
<option value="4">Lemon - Out of stock</option>
<option value="5">Melon - Out of stock</option>
<option value="6">Watermelon</option>
</select>
leek1234
  • 470
  • 2
  • 9

3 Answers3

2

I've looked through a bunch of duplicates like this but didn't like the answers that much, so I'm writing my own.

The easiest way is to remove the options in question, then append them again. This will move them to the end, in order.

Here's example code:

document.querySelectorAll('.form-dropdown').forEach(function(select) {
  Array.from(select.options).forEach(function(option) {
    if (option.innerText.includes("Out of stock")) {
      select.removeChild(option);
      select.appendChild(option);
      option.setAttribute("disabled", true);
    }
  });
});
<select class="form-dropdown">
  <option disabled="" value="">Choose option</option>
  <option value="0">Apple</option>
  <option value="1">Banana</option>
  <option value="2">Cherry - Out of stock</option>
  <option value="3">Kiwi</option>
  <option value="4">Lemon - Out of stock</option>
  <option value="5">Melon - Out of stock</option>
  <option value="6">Watermelon</option>
</select>
0

The best way to do this would be to sort the items before you add them as HTML, but here I've removed them from the HTML & then sorted & then re-applied tp HTML.

for (const element of document.querySelectorAll(".form-dropdown option")) {
  element.dataset.product = element.innerHTML;
}

document.querySelector(".form-dropdown option[data-product='Cherry - Out of stock']").classList.add('outOfStock');

const select = document.querySelector('select');

const options = document.querySelectorAll('option');

const sortOptions = [];

      options.forEach(option => sortOptions.push(option));
      
      sortOptions.sort((a,b) => a.innerHTML.indexOf('- Out') > -1 ? -1 : 1);
      
      select.innerHTML = '';
     
      sortOptions.forEach(option => select.appendChild(option));
<select class="form-dropdown">
<option disabled="" value="">Choose option</option>
<option value="0">Apple</option>
<option value="1">Banana</option>
<option value="2">Cherry - Out of stock</option>
<option value="3">Kiwi</option>
<option value="4">Lemon - Out of stock</option>
<option value="5">Melon - Out of stock</option>
<option value="6">Watermelon</option>
</select>
user3094755
  • 1,561
  • 16
  • 20
0

The others answers here show how you can sort an existing element. So as you asked for suggestions, I'd actually suggest not to hardcode select options, but to create an array of objects and dynamically generate the selection instead. Like so:

<!DOCTYPE html>
<html lang="en">
<head></head>
<body>
    <select class="form-dropdown">
        <option disabled="" value="">Choose option</option>
    </select>
    <script>
        let products = [
            {name: "Apple", inStock: true},
            {name: "Banana", inStock: true},
            {name: "Cherry", inStock: false},
            {name: "Kiwi", inStock: true},
            {name: "Lemon", inStock: false},
            {name: "Melon", inStock: false},
            {name: "Watermelon", inStock: true}
        ]

        products.sort((a, b) => {
            if(a.inStock) {
                return -1
            }
        })

        var menu = (document.getElementsByClassName("form-dropdown"))[0]

        products.forEach(item => {
            var opt = document.createElement("option")
            opt.value = item.name

            if(item.inStock) opt.text = item.name
            else opt.text = item.name + " - Out of Stock"

            menu.add(opt)
        })
    </script>
</body>
</html>
almarc
  • 1,598
  • 3
  • 11
  • 31