New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Prevent select2:open when clearing selection #3320
Comments
This feature "makes" weird solutions to prevent it: http://stackoverflow.com/questions/29618382/disable-dropdown-opening-on-select2-clear |
I did manage to implement this functionality by trapping the |
I can confirm this issue. I think this issue should be considered a bug, since when a user wants to clear the select, he does not immediately want to select another value. And if he does, he would simply click on the element anywhere but the clear button. |
@kartik-v Could you please explain what you do exactly? I tried cancelling the opening event using e.preventDefault(). This works, but I do get a JavaScript error My code as I now have it:
@kevin-brown What is the reason for the new behaviour? Is it possible to restore the old behaviour, potentially as an option? |
Known issue, tracking at #3431.
Based on the commit (ffed370), there wasn't any major reason for it.
I'm open to the idea of it, though it would have to be done in a way such that it didn't break backwards compatibility. |
Yes its similar to yours (probably yours is better) - and more of an hack - which you can check on my Yii2 Select2 widget demo pages - but I am also facing the args undefined message as you mentioned (probably only when I have change events on the input) and related to #3431. At other times I am getting an error // initialize a variable like this (better if this variable is unique for each Select2 input)
var isClearClicked = false;
// trap these events
$field.on('select2:opening', function(e) {
if (window['isClearClicked']) {
e.preventDefault();
window['isClearClicked'] = false;
}
}).on('select2:unselect', function(e) {
window['isClearClicked'] = true;
}); |
I modified the hack to the following code combining all the thoughts in this thread (with some additions) and it seems to work without errors (if you can forgive the flicker of open and close of the dropdown) - so still a dirty hack... till we get this solved... var $el = $('#select-id');
$el.on('select2:opening', function(e) {
if ($el.data('unselecting')) {
$el.removeData('unselecting');
setTimeout(function() {
$el.select2('close');
}, 1);
}
}).on('select2:unselecting', function(e) {
$el.data('unselecting', true);
}); |
Another side effect of clear - #3452 - we probably need additional events. |
The following works for me: $("select").on("select2:unselecting", function (e) {
$(this).select2("val", "");
e.preventDefault();
}); |
I agree with others, this is odd default behaviour - it doesn't match the default behaviour of the standard multiselect HTML element on Windows (Chrome, FF and standard Office and Windows UI tested) or MAC, and in our focus group test of our new UI, it confused and frustrated users (as they had to do an additional click to access options below the select2 element after they had cleared all the selected items from the multiselect) Further to this is is a change in behaviour from Select2 v3, so yet another incompatibility - with no evidence supported reason for the change :( I would like to see the default behaviour changed to match v3, or at the very least a option for it. @NovaFocus solution doesn't appear to work when the select is configured for multiselect |
Here's another hack for those that can't stand the quick flicker that shows up in kartik's solution (full credit to him for his solution being a springboard to this solution):
|
👍 for making it to not open the dropdown. Maybe an option like "autoOpenOnClear" could solve the issue. Or people could trigger the opening theirselves with the unselecting event? |
@SectorNine50 your solution works, but disables the normal opening of the dropdown for one click after unselecting from the dropdown list, so i came up with this, witch i think works better because it prevents the open event from firing in the first place: var select2Obj = $('select');
select2Obj.select2();
select2Obj.on('select2:unselecting', function(e) {
$(this).on('select2:opening', function(e) {
e.preventDefault();
});
});
select2Obj.on('select2:unselect', function(e) {
var sel = $(this);
setTimeout(function() {
sel.off('select2:opening');
}, 1);
}); Obviously, replace " sel.off('select2:opening'); " with your own code for taht event if you're using it |
@Hlsgs Odd, it doesn't have that behavior on my end... Both of the That said, what you came up with is a good solution as well! |
@SectorNine50 unfortunately, i don't know how to watch for variables that are not defined straight in js. btw, how would one watch for unselecting1 and unselecting2 in your code? regardless, i think this behaviour is because unselecting by clicking the "x" in teh selection actually reopens the dropdown but unselecting from the dropdown does not. so after unselecting we're left with one more round of preventing teh dropdown from opening. i've dug a little deeper here, and decided to fix select2.js as per here 6be96cf and use preventdefault() as TypeError: args is undefined is a select2 issue and this is going to be in future releases anyway.
This produced exactly the same results as your vanilla solution, and after deselecting from the dropdown the opening of it gets blocked for a round. In the end i went back to my solution, as it doesn't rely on setting variable and, by hooking into the :unselect event to restore opening functionality it disregards wether the dropdown was actually opened or not. And the timeout accounts for the opening event firing more than once(or not). Considering all this, i should be fine with this solution even if in future updates open fires only once and/or the developer prevents the opening of the dropdown in the original code. Correct? EDIT: $(this).on('select2:unselecting', function(e) {
$(this).on('select2:opening', function(event) {
event.preventDefault();
});
});
$(this).on('select2:unselect', function(e) {
var sel = $(this);
setTimeout(function() {
sel.off('select2:opening');
}, 100);
}); and this doesn't: $(this).on('select2:unselecting', function(e) {
$(this).on('select2:opening', function(event) {
event.preventDefault();
});
});
$(this).on('select2:unselect', function(e) {
var sel = $(this);
sel.off('select2:opening');
}); |
Within your debugger, you should be able to dig into the parent variable
If future versions only fire open once or not at all, you'll have to change the code, since one (or both) variable(s) will still remain set, meaning that the next attempt to open will be blocked. I'm not entirely sure what your patch changes, honestly. I'll have to dig a little more into the core code to get an understanding. |
+1 for this...great component anyway |
Works great, thanks |
Still no solution? |
The planned solution is to add a |
Please don't close this if unresolved. |
Still not fixed in 4.0.8 |
Yup, this can be done natively. I followed the guidance at #3320 (comment) and made a jsbin for everyone. https://jsbin.com/duyisusawo/edit?html,js,output $("select").on("select2:clear", function (evt) {
$(this).on("select2:opening.cancelOpen", function (evt) {
evt.preventDefault();
$(this).off("select2:opening.cancelOpen");
});
}); I'm going to turn this ticket into a documentation ticket, so this snippet can be added to the documentation for others to use. |
Thanks. Is there a reason this feature cannot be included within the plugin by default instead of one needing to write this code for every select2 plugin render? |
Yes, there's actually a pretty solid reason: maintenance. The snippet takes a few minutes to copy and install globally (you don't need to copy/paste it for each one, it'll only affect The external event system exists for others to be able to integrate with Select2 and allow it to do things which are not natively supported. This is an awesome example of one of those cases. |
Another boolean option is not needed if the default behavior were to not open the dialogue on clear, which seems much more sensible especially for multiselect. If I click clear I mean clear, not clear and open just so I have to close it. As it stands I have to double-check that every single time I setup a select2 control (often dynamically, on many pages) I also ensure this event hook is attached. |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
I'm surprised that this is a "feature". We switched to select2 recently and testing feedback was that this issue is a bug. Kind of disappointing that I have to wrangle events just to get around this behaviour. |
Simple and worked! |
Hello, yes it worked for me, but unfortunately it still sends AJAX request after unselecting the value( |
@nafetsrybak that sounds like a different issue and possibly a bug, any chance you can open a new ticket about it? |
We want to restore the previous behaviour and keep the options closed when clear is clicked select2/select2#3320 (comment) Signed-off-by: Katrin Fischer <katrin.fischer.83@web.de> Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
This is definitely not feature, but bug. If we will ignore fact that clear means clear and not adding as people mentioned before, here is picture what will happen if somebody clear multiple selects without @NovaFocus fix. Unfortunatelly even with @NovaFocus fix the problem is not solved. It works only for selects that are simple, not multiple. In that case when somebody wanna remove only one option, he will delete all options except the last one. Update: for those who wants clear single and multiple without dropdown here is my little trick (still need some trick when removing by backspace):
|
This works for me for preventing the dropdown from re-opening when you click clear, but prevents the dropdown from opening again at all after that. This solution worked best for me: https://stackoverflow.com/a/35807365 $('#my-select').select2({
allowClear: true
}).on('select2:unselecting', function() {
$(this).data('unselecting', true);
}).on('select2:opening', function(e) {
if ($(this).data('unselecting')) {
$(this).removeData('unselecting');
e.preventDefault();
}
}); |
Works for me. |
I came across this particular code snippet // Related with https://github.com/select2/select2/issues/3320
$(sallowClearelect).on('select2:unselecting', function() {
$(this).data('unselecting', true);
}).on('select2:open', function() {
if ($(this).data('unselecting')) {
$(this).select2('close').removeData('unselecting');
}
}); which links to this ticket. Unfortunately this hack influences the behavior of the select2 tags plugin negatively. Usually, it would just start removing the last letter of the previous tag when using the backspace key. With this "hack" it removes the whole "tag" :( |
After digging for a bit I found a solution and changed a few things, idk if this'd work for y'all
|
Prevent catching the click (and disallow opening of the select or triggering the
select2::open
) when the clear indicator is pressed to clear the selection whenallowClear
istrue
.This behavior worked fine in 3.5.2 - not sure if there is a reason for this.
Use case: When
allowClear
istrue
and one clicks the selection clear indicator -- the value gets cleared but it also triggers the dropdown to open again when it is not necessary.The text was updated successfully, but these errors were encountered: