I have this two selects, where I only have to select one at a time:
<div >
<div >
<label>Geo Blacklist</label>
<select name="blacklist[]" multiple="multiple" id="blacklist"
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 >
<div >
<label>Geo Whitelist</label>
<select name="whitelist[]" multiple="multiple" id="whitelist"
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?
CodePudding user response:
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 >
<div >
<label>Geo Blacklist</label>
<select name="blacklist[]" multiple="multiple" id="blacklist"
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 >
<div >
<label>Geo Whitelist</label>
<select name="whitelist[]" multiple="multiple" id="whitelist"
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>
CodePudding user response:
This issue is with select2. 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 select2 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 id='opt1'>
<option value="AL">Alabama</option>
<option value="AK">Alaska</option>
<option value="AZ">Arizona</option>
</select>
<select id='opt2'>
<option value="AL">Alabama</option>
<option value="AK">Alaska</option>
<option value="AZ">Arizona</option>
</select>