1

I'm using Select2 with jQuery to build a dependent relationship between SELECT elements on a form. I'm trying to build the typically relation: Country has States, States has Cities, City has Town and so on. Right now I'm doing in this way:

$(document).ready(function() {
    $(".pais").on('change', function() {
        pais = $(this).find('option:selected').val();
        $.get(Routing.generate('estados', {pais_id: pais})).success(function(data) {
            if (data.message === "") {
                $('.estado').empty().append('<option value="-1">Seleccione un estado</option>');
                $.each(data.entities, function(i, d) {
                    $('.estado').append('<option value="' + d.id + '">' + d.nombre + '</option>');
                });

                $('.estado').removeAttr('disabled');
                $('.estado').next('span').remove();
                $('.estado').closest('.form-group').removeClass('has-error');
                $('.estado').select2();
            } else {
                $('.estado').next('span').remove();
                $('.estado').closest('.form-group').addClass('has-error');
                $('.estado').after('<span class="help-block">' + data.message + '</span>');

                $('.estado').empty().append('<option value="-1">Seleccione un estado</option>').attr('disabled', 'disabled');
                $('.municipio').empty().append('<option value="-1">Seleccione un municipio</option>').attr('disabled', 'disabled');
                $('.ciudad').empty().append('<option value="-1">Seleccione un ciudad</option>').attr('disabled', 'disabled');
                $('.parroquia').empty().append('<option value="-1">Seleccione un parroquia</option>').attr('disabled', 'disabled');
            }
        }).error(function(data, status, headers, config) {
            if (status == '500') {
                message = "No hay conexión con el servidor";
            }
        });
    });

    $(".estado").change(function() {
        estado = $(this).find('option:selected').val();

        $.get(Routing.generate('municipios', {estado_id: estado})).success(function(data) {
            ...
        }).error(function(data, status, headers, config) {
            ...
        });

        $.get(Routing.generate('ciudades', {estado_id: estado})).success(function(data) {
            ...
        }).error(function(data, status, headers, config) {
            ...
        });
    });

    $(".municipio").change(function() {
        municipio = $(this).find('option:selected').val();

        $.get(Routing.generate('parroquias', {municipio_id: estado})).success(function(data) {
            ...
        }).error(function(data, status, headers, config) {
            ...
        });
    });
});

But when I change the same SELECT "Estado" or "Ciudad" or "Municipio" or "Parroquia" twice or more times I got this error:

uncaught exception: query function not defined for Select2 s2id_municipio

Note: I changed "Estado" more than one time to get this error in case you can try to reproduce the same error

Maybe the error is in my logic or maybe not so I need some help here and my question is: it's possible to build nested dependent SELECT (applying Select2 of course) with AJAX calls for build the same structure?

You can take a look to live example in this link choose any option for example "Persona Natural" and then at "Datos Personales" at "Pais de Residencia" choose "Venezuela" and then try to change the "Estado" field two or more times and see what's happen, any advice on this?

PS: Sorry for Spanish language on some parts this is a job for a Spanish client and he hates English (don't ask me why)

ReynierPM
  • 17,594
  • 53
  • 193
  • 363
  • 1
    possible duplicate of ["query function not defined for Select2 undefined error"](http://stackoverflow.com/questions/14483348/query-function-not-defined-for-select2-undefined-error) – Kevin Brown-Silva Aug 22 '14 at 16:36

2 Answers2

1

You should really be using Select2's AJAX functionality instead of doing it on your own. This means changing the underlying elements from <select> to <input type="hidden" /> and pointing Select2 at your data source.

https://ivaynberg.github.io/select2/#ajax

Here is an example of how to convert the states drop down.

var $pais = $("select.pais");
var $estados = $("input.estados");

$estados.select2({
    placeholder: "Seleccione un estado",
    ajax: {
        url: function () {
            var pais = $pais.val();
            return Routing.generate('estados', {pais_id: pais});
        },
        results: function (data) {
            return {
                results: data.entities
            };
        }
    },
    formatNoResults: function () {
        return "No se encontraron estados para el país actual";
    }
    formatAjaxError: function () {
        return "No hay conexión con el servidor";
    }
}).select2("enable", false);

Note that I am using $("input.estados") for the selector instead of just the class. This is because Select2 will copy the class to the Select2 container, and that will cause problems when referencing it again as you get multiple elements. This is explained a little more in this answer.

Community
  • 1
  • 1
Kevin Brown-Silva
  • 40,873
  • 40
  • 203
  • 237
0

This gist is an easy to use JS class for making Select2 list boxes dependent. For example -

new Select2Cascade($('#parent'), $('#child'), '/api/to/load/:parentId:/childs');

Check the demo on codepen. Also here is a post on how to use it.

Anis
  • 3,349
  • 1
  • 21
  • 16
  • I got this error bro TypeError: b.dataAdapter is null – Somwang Souksavatd Nov 15 '17 at 18:04
  • @SomwangSouksavatd, Thanks for asking, but it's hard to comment based on this little description. Can you please share more details? A sample on Codepen of JSFiddle can be helpful. – Anis Nov 18 '17 at 13:09