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
In multi-select, selections do not appear in the order in which they were selected #3106
Comments
I'm not quite sure what you mean here. For me, the tags are appended to the end of the selection when they are created. In the dropdown, they appear at the bottom after they are created, and at the top when they do not yet exist. |
Ah, now I understand. The order that the items are displayed is the same order that they will be sent to the server. This is also the same order that they are displayed in the dropdown (usually). |
That's..... huh? Why would you want tags to appear in a different place than the cursor position? The dropdown position is not relevant to the order in which I add tags. I could see them rearranged in a certain order on page reload, but while typing / selecting is jarring. If you add emails to an email, your email program doesn't swap the tags based on alphabetical position. It represents a linear, comma-separated list that just happens to be tokenized for easy removal of items, or to drag/drop items, or match to a list. I don't get this behavior. OR: if this is intuitive to others, can linear append be an option? |
Usually when working with tagging, there isn't an existing data set or it's pulled from a remote data source when there is (which is unordered on our end). In both of these cases, new additions are always appended to the end. You can test this by always creating new tags and seeing the order that they appear once they are selected. It should be in the order that they were created, and they should be sent to the server in that same order. If this isn't the case, then yes there is definitely an issue. The difficulty comes when there are new additions to the end and then an existing one is selected, as it most likely isn't at the end as well. There used to be complaints (which made sense) because what was displayed did not match what was being sent to the server, as the ordering was off. |
If you tag a post in Wordpress, you can add arbitrary members, but you can also select from a list of tags. Either way, selections are added linearly as that's the way they were selected chronologically. Tags always indicate the order in which a user selected them (or typed them). This is done because a backspace then deletes them from right-to-left reverse chronologically. Or you could say it's done because of left-to-right reading conventions corresponding to order of operations. If the complaint is that the ordering to the server doesn't match the selection order, then I would change the ordering sent to the server. OR allow a switch to the current behavior of partial sorting of tags within the list by two sets of criteria (matches and non-matches, the first sorted by list order, the second by chronological selection order), but I would expect that to be the outlier in terms of expected behavior, since a two-method partial-list-sort algorithm seems hard to intuit. In fact, at first I thought the list was completely randomized each time, until I figured out that the list was invisibly divided between matches and non-matches, with each one sorting independently by different criteria. So.... select2 is a great component. I'd really like to use it more. Can another option be added? |
So, ultimately the issue here is that Select2 is trying to normalize how the results are displayed to match how the data is sent to the server. This is because that previously wasn't consistent (or documented) and it had some really strange side effects ("what you see is not what you get") and inconsistencies ("only when working with a
Great idea! I just took a shot at doing this by automatically re-inserting the most recently selected element to the end of the http://jsbin.com/cizehajema/1/edit Of course, this means that now the results list changes every time, because the |
I think a few things are being conflated. For example, this:
The drop-down order shouldn't really have anything to do with tag order. The tags (tokens) are the order of selection. The drop down is really the fixed dataset, usually alphabetical or whatever the sort method was. If the drop down is being populated BY arbitrarily-added tags, then it probably makes some sense, and in that case the drop-down should mimic selection order. (Although I can't think of a case where having arbitrary added values in the drop-down makes sense anyway. It seems like the dropdown is only useful when it shows imported data, not user-added data.) But, if, say, the dataset is an imported list of U.S. states., then of course the selected tags should never re-order the drop-down, because it's a fixed list of available options. So, I think it's important to have three distinct datasets:
It sounds like 1 and 3 need to be synced to avoid confusion, but number 2 needn't be. Just my $0.02. |
Yeah it looks like that's another select2 oddity here...
+1. That's definitely the expected behavior. |
Also when using multiple= true (no tags), the order that I would like to have is not the order in which the options are ordered but the order in which the user is selecting the options. Any ideas about this? |
+1 on @janscas's concern. It's particularly problematic when adding a tag by mistake then pressing backspace to remove it, if the tag is inserted in another position, you'll start deleting the wrong tag |
I just ran into the issue that on server-side I need the order in which the items were selected. I wrote a simple script that just reorders the options inside the select every time, an item is selected: $this.on('select2:select', function(e){
var elm = e.params.data.element;
$elm = jQuery(elm);
$t = jQuery(this);
$t.append($elm);
$t.trigger('change.select2');
}); Here is also a JsFiddle. |
@kevin-brown Your code worked for me except the unselect. The unselected item was getting removed completely after you add/remove it multiple times. `$("select").select2({
|
Hi How to make this work as i already have a $element with the select2 object
Now how do i hook into this with above code example? Please assist. Thank you. And another question. Will their be a update of the script where the multiselect select order is adjustable? And how to load the correct order of the selected items on modification of the items? My list of options is created in php where the selected=selected is set based on the setting stored in the database. this is how my code looks on init But they were selected this way b|infomation,p|document,s|building
What i want is to have the result screen to present the order of the items as they are selected once the data-order="true" Best regards, |
I think I solved that by adding custom DataAdapter which:
Adapter inherits native methods which don't have specified API visibility (public/ protected) so there is no guarantee it will work in future versions. Tested on Select2 v4.0.2 See this gist |
Hi, The Adapter works, but it's not possible to create tag anymore (it's only possible to choose an existing one). Would you have a solution for that ? Thank you |
// with this element...
$("select").select2({
tags: true,
tokenSeparators: [',', ' '] // note: doesn't work for these! hitting comma or space will reorder tags
});
// apply tag order fix
$("select").on("select2:select", function (evt) {
var element = evt.params.data.element;
var $element = $(element);
$element.detach();
$(this).append($element);
$(this).trigger("change");
}); |
@benjiwheeler Unfortunately, that approach (also found here: http://stackoverflow.com/questions/31431197/select2-how-to-prevent-tags-sorting) does not maintain the order of the options list. Select a value from the list and another; notice it preserves the selection order, but that also modifies the selection list. Clear them and try to select them via mouse again and notice they appear at the end of the options list (no longer in the original sort). |
@kevin-brown While this is great from a developer's standpoint, this is assuming that the select data is being sent to the server. In many cases, select options are used for UI to modify the data internal to the page and not even sent to the server. For those cases, this is very confusing. Better UX is to display the data as it is selected and not make the user hunt through the selected options to verify that it was selected. If a developer needs to preserve that order when sending to the server, they will need to account for that in their AJAX or form submission event. |
|
@Tagirijus unfortunately, not a single of the workarounds @Oliboy50 refers to works at the moment without side effects that render the select box unusable in one way or the other. https://github.com/jshjohnson/Choices might be a solution for your use case. It's a dependency-free multi-select library. For my use cases it worked well and solves the order problem. |
Hey, @artjomsimon , thanks for the hint. I will have a look. (= |
@artjomsimon Choices looks nice, good to be able to specify shouldSortItems: false without a workaround...
|
@Tagirijus I posted a solution earlier that works. I imagine it's not being adopted because it contains more lines of code, but it is also more robust than most of the solutions posted here. There was a race condition for some reason, which AJAX introduced, which I have since patched with a timeout. You can view it here: When wanting to retrieve the values in presented order it is important to use |
Thanks for the reply. I'll check it out, if I have some time. |
For remote data I was solved problem with help schang933 message #3106 (comment). Thank you. |
We don't have immediate plans to provide this. We are focused to fix some major UI bugs (that are majority of issues and PR's). But if you open a PR with unit tests, I will be glad to review and approve if everything is ok 👍 |
I'm facing the problem when using customAdapter, were I clicked if I removed customAdapter working fine. |
none of above provided sugestions worked for me, finally came to this solution: //allow ordering
}) |
the function for reordering after deselect should be: |
if you try to set a value to selected (ex: <option selected four>) you will see that when try to add a new value (ex: two) ... and you will see that value will disappear! |
I am using icon/image and ,it only worked with double quotes . $(e.target).children('[value="'+id+'"]'); |
The solution from @ercanertan works well (original solution from @2rba). |
These follow-up solutions are solving one problem or another, but not most of the problems all at once. For anyone reading this (untested on newer version of Select), I still recommend tracking and applying the preserved order during selection and unselection as mentioned here: #3106 (comment) It is important for the ordering in the dropdown to remain in tact, while the selection order (and sent to the server) reflects the order the items are selected/displayed. It is also important for this process to be reset and undone. |
+1 please add this feature Meanwhile - workaround This worked for me:After much hacking around - this hack messes around with the Select2 display elements directly, namely the
|
…roposal to resolve select2#3106 with some limitations for manual selection changes (as noted). - This class has to keep both display and selection ordering for all options in order to manage selection order, while maintaining the default results/query ordering (when `sorter` is not used, etc). - Notable but unfortunate limitation: Setting the control value using `jQuery.val([...])` with multiple items or manually toggling option `selected` (without a `change` event) still cannot preserve the value ordering. - The partial workaround for this is to manually set your selected options with the `data-selection-order` attribute before setting val() if possible. - It may also be possible to enhance the decorator to watch for manual changes via MutationObserver. TBD. New options: - `keepSelectionOrder` - `trackManualSelectionOrder` Update docs. Add tests.
I found a quite good solution, with version 4.0.13 (i'm not sure about the older one) we can attach a sorter function that is executed when you open the dropdown, so I basically created my own custom sorter and every time I open the dropdown I sort it alphabetically. For the select event, this code is to append the last selected item to the end of the input list.
and for the sorter, you can pass a function as an option and it's called in the Results.prototype.sort of Select2.
Sorter function receive the data (array of objects that is used to create the options), I use my custom sort method to order alphabetically before return it.
I think it's an easy solution, and it is working well in my scenario. |
@guisantos Your approach generally works fine unless you also want the field's value via things like |
If you're interested, you can see multiselect selection order issue here: select2/select2#3106 We don't use the solution there, since I couldn't find perfect solution there. So we built our solution to match our need.
var select = $('#input_select_abc');
select.on('select2:unselecting', function (event) {
console.log('unselecting:', event.params.args.data.id);
select.find('option[value="' + event.params.args.data.id + '"]').remove();
}); |
maybe I'm too far-away late and this topic looks out-of-date, but here is my code:
what I do in here is i found answer from @kevin-brown and copy-paste from http://jsbin.com/cizehajema/2/edit and improve some logic. in the end, when the user clicked option, find where the oldest to latest choice then order it by latest choices. And it will appear in the first choices. Take a look at my example screenshot here: ADDITION:
the final result is approxiately like this below: thank you |
On this page: https://select2.github.io/examples.html
...All the tags appended to the end show up in an arbitrary place in the Select2 box. There seems to be no rhyme or reason where they will appear, neither alphabetical nor sorting by list matching. It just randomly sorts each time. This seems to be the reverse of issue #2283, so I'm not sure how to actually force the tags to append.
The text was updated successfully, but these errors were encountered: