levipadre
levipadre

Reputation: 619

Reinit select2 data

I would like to re-init data value for region select when country select's selected value is Canada. Otherwise region list should stay default, so Us regions.

So far I have the following code, but it always stay US regions. I tried to destroy and re-init again as well, but without any success, unfortunately.

var countriesList = 'https://cdn.jsdelivr.net/npm/world_countries_lists@latest/data/en/countries.json',
    regionsList = 'https://rawcdn.githack.com/levipadre/US-and-Canada-states-json/de677490123474288ae2777d04f1728e1f1833a9/us-states.json',
    countrySelect = $('.country'),
    regionSelect = $('.region');

$.ajax({
    type: 'GET',
    url: countriesList,
    dataType: 'json',
    success: function(response) {
        countrySelect.select2({
            data: response.map(item => ({
                id: item.alpha2,
                text: item.name
            })),
            width: '100%',
            dropdownAutoWidth: true,
            matcher: startWithMatcher,
            placeholder: 'Select country'
        });
    }
});

countrySelect.on('select2:select', function (e) {
    var data = e.params.data;
    
    console.log(data.id);
    if(data.id == "ca") {
        regionsList = 'https://rawcdn.githack.com/levipadre/US-and-Canada-states-json/de677490123474288ae2777d04f1728e1f1833a9/canada-states.json';
        getRegion(regionsList);
    } else {
        getRegion(regionsList);
    }
});

function getRegion(region){
    $.ajax({
        type: 'GET',
        url: region,
        dataType: 'json',
        success: function(response) {
            regionSelect.select2({
                data: response.map(item => ({
                    id: item.id,
                    text: item.text
                })),
                width: '100%',
                dropdownAutoWidth: true,
                matcher: startWithMatcher,
                placeholder: 'Select region'
            });
        }
    });
}

getRegion(regionsList);

function startWithMatcher(params, data) {
    params.term = params.term || '';
    if (data.text.toUpperCase().indexOf(params.term.toUpperCase()) == 0) {
        return data;
    }
    return false;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/css/select2.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/js/select2.min.js"></script>

<select class="country">
  <option></option>
</select>

<br>
<br>
<br>

<select class="region">
  <option></option>
</select>

Upvotes: 1

Views: 194

Answers (1)

Rory McCrossan
Rory McCrossan

Reputation: 337560

Your current logic is appending the new regions to the select2 instance. To remove the original entries you can call empty() on the select before you add the new option elements. Alternatively, if you want to retain the first empty option, then you can use this:

regionSelect.children().not(':first').remove();

Here's a working example:

var countriesList = 'https://cdn.jsdelivr.net/npm/world_countries_lists@latest/data/en/countries.json',
  regionsList = 'https://rawcdn.githack.com/levipadre/US-and-Canada-states-json/de677490123474288ae2777d04f1728e1f1833a9/',
  countrySelect = $('.country'),
  regionSelect = $('.region');

$.ajax({
  type: 'GET',
  url: countriesList,
  dataType: 'json',
  success: function(response) {
    countrySelect.select2({
      data: response.map(item => ({
        id: item.alpha2,
        text: item.name,
        source: item.alpha2 == 'ca' ? 'canada-states.json' : 'us-states.json'        
      })),
      width: '100%',
      dropdownAutoWidth: true,
      matcher: startWithMatcher,
      placeholder: 'Select country'
    });
  }
});

countrySelect.on('select2:select', function(e) {
  var data = e.params.data;
  regionSelect.show();
  getRegion(regionsList + e.params.data.source);
});

function getRegion(region) {
  $.ajax({
    type: 'GET',
    url: region,
    dataType: 'json',
    success: function(response) {
      regionSelect.children().not(':first').remove(); // remove old options
      regionSelect.select2({
          data: response.map(item => ({
            id: item.id,
            text: item.text
          })),
          width: '100%',
          dropdownAutoWidth: true,
          matcher: startWithMatcher,
          placeholder: 'Select region'
        });
    }
  });
}

function startWithMatcher(params, data) {
  params.term = params.term || '';
  if (data.text.toUpperCase().indexOf(params.term.toUpperCase()) == 0) {
    return data;
  }
  return false;
}
.region { display: none; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/css/select2.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/js/select2.min.js"></script>

<select class="country">
  <option></option>
</select>
<br /><br />
<select class="region">
  <option></option>
</select>

Also note that I fixed your logic to allow changing between US/Canadian states, as the original logic would always retain Canadian once changed.

Upvotes: 1

Related Questions