skip to Main Content

I have this two selects, where I only have to select one at a time:

<div class="col-md-12">
    <div class="form-group">
        <label>Geo Blacklist</label>
        <select name="blacklist[]" multiple="multiple" id="blacklist"
            class="form-control select2"
            data-placeholder="Seleccionar uno o varios países" tabindex="1"
            onchange="$('#whitelist').val([]).change();">
            <option>a</option>
            <option>b</option>
            <option>c</option>
        </select>
    </div>
</div>

<div class="col-md-12">
    <div class="form-group">
        <label>Geo Whitelist</label>
        <select name="whitelist[]" multiple="multiple" id="whitelist"
            class="form-control select2"
            data-placeholder="Seleccionar uno o varios países" tabindex="1"
            onchange="$('#blacklist').val([]).change();">
            <option>x</option>
            <option>y</option>
            <option>z</option>
        </select>
    </div>
</div>

When I select anyone I get:

Uncaught RangeError: Maximum call stack size exceeded
at RegExp.exec ()
at [Symbol.replace] ()
at String.replace ()
at Function.camelCase (jquery.js:346:17)
at Function.style (jquery.js:6643:22)
at jquery.js:6866:12
at jQuery.access (jquery.js:4142:5)
at jQuery.fn.init.css (jquery.js:6849:10)
at Search.resizeSearch (select2.full.js:2032:18)
at DecoratedClass.resizeSearch (select2.full.js:580:32)

How can I do this?

2

Answers


  1. Just remove .change() as it trigger the change event on the other select and make infinite loop

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div class="col-md-12">
                <div class="form-group">
                    <label>Geo Blacklist</label>
                    <select name="blacklist[]" multiple="multiple" id="blacklist"
                        class="form-control select2"
                        data-placeholder="Seleccionar uno o varios países" tabindex="1"
                        onchange="$('#whitelist').val([]);">
                        <option>a</option>
                        <option>b</option>
                        <option>c</option>
                    </select>
                </div>
            </div>
            
            <div class="col-md-12">
                <div class="form-group">
                    <label>Geo Whitelist</label>
                    <select name="whitelist[]" multiple="multiple" id="whitelist"
                        class="form-control select2"
                        data-placeholder="Seleccionar uno o varios países" tabindex="1"
                        onchange="$('#blacklist').val([]);">
                        <option>x</option>
                        <option>y</option>
                        <option>z</option>
                    </select>
                </div>
            </div>
    Login or Signup to reply.
  2. This issue is with . When changing a <select> value that’s been select2-ised, you have to call .change() to update the UI.

    This then triggers the 2nd select change event, which calls .change etc, creating an infinite loop as shown with Maximum call stack size exceeded.

    You can’t simply remove the .change() as that would then not update the UI.

    The solution is described in the select2 documentation

    It’s common for other components to be listening to the change event, or for custom event handlers to be attached that may have side effects [such as an infinite loop]. To limit the scope to only notify Select2 of the change, use the .select2 event namespace:

    $('#mySelect2').val('US');
    $('#mySelect2').trigger('change.select2'); // Notify only Select2 of changes
    

    In the case of this question that would be to change

    onchange="$('#blacklist').val([]).change();">
    

    to

    onchange="$('#blacklist').val([]).trigger('change.select2');">
    

    (and the same for whitelist)

    Here’s a snippet (and fiddle) that demonstrates change.select2. Edit and change from change.select2 to change and you get the infinite loop.

    $('.select2').select2();
    
    $('#opt1').on('change', function() {
      console.log($(this).val())
      $("#opt2").val([]).trigger("change.select2");
    });
    $('#opt2').on('change', function() {
      $("#opt1").val([]).trigger("change.select2");
    });
    <link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.4/css/select2.min.css" rel="stylesheet" />
    <script src="//code.jquery.com/jquery-2.2.4.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.4/js/select2.min.js"></script>
    
    <select class="select2" id='opt1'>
      <option value="AL">Alabama</option>
      <option value="AK">Alaska</option>
      <option value="AZ">Arizona</option>
    </select>
    
    <select class="select2" id='opt2'>
      <option value="AL">Alabama</option>
      <option value="AK">Alaska</option>
      <option value="AZ">Arizona</option>
    </select>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search