Skip to content

Instantly share code, notes, and snippets.

@ajaxray
Last active June 1, 2025 08:01
Show Gist options
  • Save ajaxray/187e7c9a00666a7ffff52a8a69b8bf31 to your computer and use it in GitHub Desktop.
Save ajaxray/187e7c9a00666a7ffff52a8a69b8bf31 to your computer and use it in GitHub Desktop.
Making Select2 (4.x) list boxes cascading / dependent. Options of a select2 list box will be loaded/refreshed by ajax based on selection of another select2 list box.
/**
* A Javascript module to loadeding/refreshing options of a select2 list box using ajax based on selection of another select2 list box.
*
* @url : https://gist.github.com/ajaxray/187e7c9a00666a7ffff52a8a69b8bf31
* @auther : Anis Uddin Ahmad <anis.programmer@gmail.com>
*
* Live demo - https://codepen.io/ajaxray/full/oBPbQe/
* w: http://ajaxray.com | t: @ajaxray
*/
var Select2Cascade = ( function(window, $) {
function Select2Cascade(parent, child, url, select2Options) {
var afterActions = [];
var options = select2Options || {};
// Register functions to be called after cascading data loading done
this.then = function(callback) {
afterActions.push(callback);
return this;
};
parent.select2(select2Options).on("change", function (e) {
child.prop("disabled", true);
var _this = this;
$.getJSON(url.replace(':parentId:', $(this).val()), function(items) {
var newOptions = '<option value="">-- Select --</option>';
for(var id in items) {
newOptions += '<option value="'+ id +'">'+ items[id] +'</option>';
}
child.select2('destroy').html(newOptions).prop("disabled", false)
.select2(options);
afterActions.forEach(function (callback) {
callback(parent, child, items);
});
});
});
}
return Select2Cascade;
})( window, $);

Select2 Cascade (for v4.x)

Loadeding/refreshing options of a select2 list box (using ajax) based on selection of another select2 list box.

Check the live demo.

How to use

Create a new instance of Select2Cascade by passing the following 4 things -

  • Parent select2 listbox
  • Child select2 listbox
  • URL to load child items from
  • (OPTIONAL) select2 options

To set the parent selected value in ajax request, keep :parentId: as a placeholder in url. The selected value of parent select2 listbox will replace the :parentId: string in url. For example -
Query string: /path/to/api?type=childType&parent_id=:parentId:
RESTful url: /path/to/api/items/:parentId:/sub-items

The response json should be a flat object of value:label pairs. e,g,

{
  "20150415" : "Chittagong Zila",
  "20190901" : "Comilla Zila",
  "20221601" : "Cox's Bazar Zila",
  "20301401" : "Feni Zila"
}

Otherwisw you have to adjust the way of populating child options (at line 29).

Examples

When #parentList is changed, call to path/to/geocode/district/SELECTED-PARENT/zilla and set the options of #childList from the ajax response.

var options = { width: 'resolve' };
new Select2Cascade($('#district'), $('#zilla'), 'path/to/geocode/district/:parentId:/zilla', options);
new Select2Cascade($('#zilla'), $('#thana'), 'path/to/geocode/zilla/:parentId:/thana', options);

If you want to do something with the response data or selectboxes, you can set (any number of) callbacks to be executed after the child listbox refreshed -

var cascadLoading = new Select2Cascade($('#parent'), $('#child'), 'path/to/api/categories?parent_id=:parentId:');
cascadLoading.then( function(parent, child, items) {
    // Open the child listbox immediately
    child.select2('open');
    // Dump response data
    console.log(items);
})
@scarroll32
Copy link

Is failing in the pen.

screen shot 2018-09-16 at 15 54 08

@ajaxray
Copy link
Author

ajaxray commented Apr 16, 2019

Hello @seanfcarroll,
Thanks for notifying! I've fixed it.
Actually, I was using https://jsonblob.com/ content as sample API response, which has been expired.
So, now I have made a gist with 2 sample json file and using their raw version as API response.

@scarroll32
Copy link

Thanks @ajaxray !

@maryjos
Copy link

maryjos commented Sep 13, 2024

Just wanted to drop of note of thanks for sharing this code. I had a fairly complex 4-selectbox cascade with different options needed for the first one (that does an Ajax lookup of its own based on the search) vs. the other 3 that populate down from that selection and was pulling my hair out trying to get it working right with Select2, this was exactly the solution I needed!

@krnsptr
Copy link

krnsptr commented Jun 1, 2025

⚠️ Security Issue: Potential XSS Vulnerability in Option Rendering

Hi Anis, thanks for sharing this useful snippet — it’s been a big help in implementing dependent Select2 dropdowns.

I noticed a potential XSS vulnerability in the following part of the code:

option += ">" + item["text"] + "</option>";

If item["text"] comes from untrusted or user-generated data, malicious users can inject <script> tags, leading to a cross-site scripting (XSS) attack.

🔒 Fix suggestion: Use a text-escaping function like:

function escapeHtml(text) {
  return $('<div>').text(text).html();
}

option += ">" + escapeHtml(item["text"]) + "</option>";

Or better yet, use jQuery’s DOM-based element creation:

var $option = $('<option>', {
  value: item.id,
  text: item.text
});

Then append it safely instead of using .html() with raw strings.

I hope this helps improve the snippet and make it safer for broader use.

Thanks again for the great work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment