select2 icon indicating copy to clipboard operation
select2 copied to clipboard

Creating a new tag with a value equal to the id of an existing option causes both the new tag and the existing option to be added as selections

Open chrisphiz opened this issue 9 years ago • 13 comments

// input: red,
// var_dump($_POST["colors"]);
Array
(
    [0] => red
    [1] => red
)

// input: apple,green,water,
// var_dump($_POST["colors"]);
Array
(
    [0] => green
    [1] => green
)

// input: red,green,blue,yellow,
// var_dump($_POST["colors"]);
Array
(
    [0] => red
    [1] => green
    [2] => blue
    [3] => yellow
    [4] => red
)
<select name="colors[]" id="tags-example" multiple="multiple">
    <option value="red">apple</option>
    <option value="green">grass</option>
    <option value="blue">water</option>
    <option value="yellow">sun</option>
</select>
$('#tags-example').select2({
    tags: true,
    tokenSeparators: [',', ' '],
    maximumSelectionLength: 2
});

Please see the following fiddle to see what happens: http://jsfiddle.net/o1je0988/

chrisphiz avatar Jun 19 '15 07:06 chrisphiz

Interesting, very interesting.

I have no idea why that's happening, but it's definitely a bug.

kevin-brown avatar Jun 19 '15 22:06 kevin-brown

This is in no way thorough, but I had a quick look and it appears to be caused by line 3098:

self.$element.val(val);

If you type in a new tag that matches an existing option value then jQuery's .val() method will set all the matching options to selected, i.e. the existing option with the same value will be selected and the newly created option will be selected. The code which displays the tags filters on (":selected"), causing both options to be shown.

The simplest fix I can think of right now would be to prefix a value to the id property when creating a new tag. Something like:

return { id: 'select2-' + term, text: term };

The idea being that you can strip out the select2- prefix server-side or even use it to identify new tags. Then there shouldn't be any value conflicts.

Just an idea, perhaps it can be expanded on.

alexalexalex-s avatar Feb 01 '18 20:02 alexalexalex-s

@kevin-brown Will the bug be fixed or is there a known workaround? Thanks for a short feedback

sebpet avatar Dec 11 '18 13:12 sebpet

@kevin-brown are you going to do something with this bug?

mszkudelski avatar May 08 '19 13:05 mszkudelski

Will this bug be fixed?

Yes, once a PR is made that fixes it. Or once someone makes a unit test that verifies the bug.

Is there a known workaround?

Not as far as I know.

kevin-brown avatar May 14 '19 23:05 kevin-brown

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.

stale[bot] avatar Jul 13 '19 23:07 stale[bot]

Renewing the call for a pull request that fixes this issue, or a unit test that verifies the bug.

kevin-brown avatar Jul 16 '19 12:07 kevin-brown

I have a workaround for this issue, this will remove the option from the select2 on unselecting if the text of the cleared option matches an options value. This will only really work if you are using an id as the value for existing options and will bug on edge cases where there is an option where the text matches the id (very rare edge case).

$select2.on('select2:unselect', function(e) { const index = [...e.currentTarget.options].findIndex(o => o.value === e.params.data.text); e.currentTarget.remove(index); });

A workaround to this edge case or if you are not using id's that I have implemented is to set a data attribute to identify a newTag on select. Then you can do the below:

$tagSelect2.on('select2:unselect', function(e) { if (e.params.data.element.dataset.newTag === 'true') { const index = [...e.currentTarget.options].findIndex(o => o.value === e.params.data.text); e.currentTarget.remove(index); } });

nmase88 avatar Jul 18 '19 10:07 nmase88

Following workaround is worked for me.

After creating select2 with tags = true option

// create select2
var select2 = $element.select2(options);
// add data-select2-tag attr to options
select2.find("option").each(function () {
    $(this).attr("data-select2-tag", true);
});

or add "data-select2-tag = true" attribute to option when adding to select

muratonnet avatar Jul 18 '19 13:07 muratonnet

Is there any plan of fixing the issue. ?

Kaushik1987 avatar Sep 05 '19 18:09 Kaushik1987

});

or add "data-select2-tag = true" attribute to option when adding to select

How it's fix the issue ? It is still same for me. can you guide me on this?

Kaushik1987 avatar Sep 09 '19 08:09 Kaushik1987

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.

stale[bot] avatar Nov 08 '19 08:11 stale[bot]

Reopening it as https://github.com/select2/select2/issues/5861 was reported.

kevin-brown avatar May 20 '20 00:05 kevin-brown