How to place a button into a select2 result item and handle its click?
Asked Answered
G

3

7

I'm trying to place a button into select2 result items (for allowing the user to remove items). I managed to place the buttons, but I didn't manage to handle their click event yet. Somehow the event doesn't get raised. I think it's something like select2 is closing the dropdown before my button's click event would raise, but cannot figure out how I could make it work.

Here is the snippet what I have now.

...    
formatResult: function (item) {
    return item.text + "<button class='btn btn-xs btn-default pull-right select2-result-button' data-id='" + item.id + "'>&times;</button>";
}
...
$(document).on("click", ".select2-result-button", function (e) {
    alert("clicked: " + $(this).data("id"));
    e.preventDefault();
    e.stopPropagation();
    return false;
});

Here is a demo fiddle. I've also tried the mousedown event without success.

Groupie answered 15/9, 2014 at 12:29 Comment(8)
An aside, but in your click handler, return false is equivalent to e.preventDefault(); e.stopPropagation().Desert
Yes I know that, I was just so confused that I wanted to be sure I try everything :)Confident
But actually when I debugged into the code I realized that the handler doesn't even get called, so it's not realted to how I prevent or not prevent it from bubbling.Confident
I would guess it is because the element seizes to exist after selection. I looked at the html while open (the 2 buttons are there) and after selection and the 2 buttons disappear!Morganmorgana
@Alexandros Yes, that's right and that is by design, because the drop down (and its content) is created on open, and destroyed on close. The problem seems to be that I'm unable to catch the click on my button before select2 would process the click and close the dropdown.Confident
@ZoltánTamási shouldn't the e.preventDefault(); e.stopPropagation(); return false; etc be on the <select> element then instead of the button? You wan't to stop the drop down from closing down right?Morganmorgana
You should have a look to this answer : https://mcmap.net/q/418619/-attach-click-event-to-element-in-select2-result. select2 prevents any click event on the popover list. But you can redefine the onSelect event like this : jsfiddle.net/qouo8uog/33.Radioactive
@SamuelCaillerie Thank you, that actually seems to do the job. I'm gonna try to put together a generic solution (adding some options like "customItemButtons" or so) based on that. If you form an answer from your comment, I'll accept it.Confident
R
4

You should have a look to this answer : https://mcmap.net/q/418619/-attach-click-event-to-element-in-select2-result : the select2 library prevents any click event on the popover list.

But you can redefine the onSelect event like this : jsfiddle.net/qouo8uog/33.

s2list.onSelect = (function (fn) {
    return function (data, options) {
        var target;

        if (options != null) {
            target = $(options.target);
        }

        // In case where the target is your own button, handle it
        if (target && target.hasClass('select2-result-button')) {
            alert("clicked: " + $(target).data("id"));
        } else {
            return fn.apply(this, arguments);
        }
    }
})(s2list.onSelect);
Radioactive answered 15/9, 2014 at 13:47 Comment(0)
G
0

At the end of the day I decided to patch the select2 source code instead of hacking the options. Probably it would be worth a pull request on the github project, but currently I have no time to prepare it.

In both of the onSelect implementations (single and multi) I've placed this code in the front.

onSelect: function (data, options) {

      // @@ implement a way to be able to place buttons in results
      // this will check if there is an event target (in case when selection is invoked by mouse/touch), and if the target is a result button, trigger the result button event on the element, and skip default selecting behaviour
      if (options && options.target && $(options.target).hasClass('select2-result-button')) {
        var evt = $.Event("select2-result-button-click", { choice: data, button: options.target });
        this.opts.element.trigger(evt);
        return;
      }
      ...
}
Groupie answered 23/9, 2014 at 8:41 Comment(0)
P
0

Just add

closeOnSelect: false

The button will works.

Phallic answered 7/3, 2023 at 0:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.