Search code examples
javascriptjquerybootstrap-selectpicker

How to sort select alphabetically which contains optgroup?


I have the following Bootstrap SelectPicker. I would like to sort all the option and optgroup alphabetically. My code doesn't seem to be working on the SelectPicker nor on a normal select. Does someone know how to do this?

var options = $('select option');
var arr = options.map(function(_, o) { return { t: $(o).text(), v: o.value }; }).get();
arr.sort(function(o1, o2) { return o1.t > o2.t ? 1 : o1.t < o2.t ? -1 : 0; });
options.each(function(i, o) {
  o.value = arr[i].v;
  $(o).text(arr[i].t);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select id="property-area" name="property_area" class="selectpicker" data-style="btn btn-primary btn-round" data-live-search="true" tabindex="-98">
  <option value="1208">Amalfi Coast</option>
  <option value="1224">Apulia</option>
  <optgroup data-id="1221" label="Tuscany">
    <option value="1302" data-parent-id="1221">Arezzo</option>
    <option value="1299" data-parent-id="1221">Argentario</option>
    <option value="1270" data-parent-id="1221">Chianti</option>
    <option value="1261" data-parent-id="1221">Florence</option>
    <option value="1297" data-parent-id="1221">Lucca &amp; Pisa</option>
    <option value="1290" data-parent-id="1221">Maremma</option>
    <option value="1283" data-parent-id="1221">Siena</option>
    <option value="1330" data-parent-id="1221">Val D'Orcia</option>
  </optgroup>
  <option value="1213">Capri Island</option>
  <option value="1249">Cilento Coast</option>
  <option value="1215">Como Lake</option>
  <option value="1253">Garda Lake</option>
  <option value="1334">Ischia Island</option>
  <option value="1257">Maggiore Lake</option>
  <option value="1234">Rome City</option>
  <option value="1308">Sicily</option>
  <option value="1205">Sorrento Coast</option>
  <option value="1218">Umbria</option>
</select>


Solution

  • You could do it with vanilla JS like this. I placed some of the last items in the dropdown as the first items, just to demonstrate.

    If you give all of them labels then you can do it like this:

    function sortStuff(arr) {
      arr.sort((a, b) => {
        if (a.label < b.label) {
          return -1;
        } else if (a.label > b.label) {
          return 1
        }
        return 0;
      })
      return arr
    }
    
    var select = document.querySelector('select')
    var options = [...select.children]
    var sortedOptions = sortStuff(options)
    
    select.innerHTML = ''
    sortedOptions.forEach(i => select.append(i))
    sortedOptions[0].setAttribute('selected', 'true')
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <select id="property-area" name="property_area" class="selectpicker" data-style="btn btn-primary btn-round" data-live-search="true" tabindex="-98">
      <option value="1218" label="Umbria">Umbria</option>
      <option value="1205" label="Sorrento Coast">Sorrento Coast</option>
      <option value="1208" label="Amalfi Coast">Amalfi Coast</option>
      <option value="1224" label="Apulia">Apulia</option>
      <optgroup data-id="1221" label="Tuscany">
        <option value="1302" data-parent-id="1221">Arezzo</option>
        <option value="1299" data-parent-id="1221">Argentario</option>
        <option value="1270" data-parent-id="1221">Chianti</option>
        <option value="1261" data-parent-id="1221">Florence</option>
        <option value="1297" data-parent-id="1221">Lucca &amp; Pisa</option>
        <option value="1290" data-parent-id="1221">Maremma</option>
        <option value="1283" data-parent-id="1221">Siena</option>
        <option value="1330" data-parent-id="1221">Val D'Orcia</option>
      </optgroup>
      <option value="1213" label="Capri Island">Capri Island</option>
      <option value="1249" label="Cilento Coast">Cilento Coast</option>
      <option value="1215" label="Como Lake">Como Lake</option>
      <option value="1253" label="Garda Lake">Garda Lake</option>
      <option value="1334" label="Ischia Island">Ischia Island</option>
      <option value="1257" label="Maggiore Lake">Maggiore Lake</option>
      <option value="1234" label="Rome City">Rome City</option>
      <option value="1308" label="Sicily">Sicily</option>
    </select>