harryg
harryg

Reputation: 24107

Select2 Event for creating a new tag

I'm using the jQuery Select2 (v4) plugin for a tag selector.

I want to listen for when a new tag is created in the select element and fire an ajax request to store the new tag. I discovered there is the createTag event but this seems to fire every time a letter is entered into the select2 element. As shown in my fiddle: http://jsfiddle.net/3qkgagwk/1/

Is there a similar event that only fires when the new tag has finished being entered? I.e. it's enclosed by a grey box enclosing it.

Upvotes: 23

Views: 33476

Answers (4)

TheVigilant
TheVigilant

Reputation: 720

One more simple check will be this based on the difference in the args of the event .....

While I was dealing with this situation, I had seen this difference; that when the new element is created the event args data does not have an element object but it exists when selecting an already available option...

.on('select2:selecting', function (e) {
   if (typeof e.params.args.data.element == 'undefined') {  
      // do a further check if the item created id is not empty..
       if( e.params.args.data.id != "" ){
          // code to be executed after new tag creation
       }
   }
 })

See this picture for different condition's event log

Upvotes: 1

Pseudo-Hippy
Pseudo-Hippy

Reputation: 197

The only event listener that worked for me when creating a new tag was:

.on("select2:close", function() {
 (my code)
})

This was triggered for new tags and selecting from the list. change, select2:select, select2:selecting and any others did not work.

Upvotes: 2

Artur Filipiak
Artur Filipiak

Reputation: 9157

I can't find any native method unfortunately. But if you're interested in simple "workarounds", maybe this get you closer:

$('.select2').select2({
    tags: true,
    tokenSeparators: [",", " "],
    createTag: function (tag) {
        return {
            id: tag.term,
            text: tag.term,
            // add indicator:
            isNew : true
        };
    }
}).on("select2:select", function(e) {
    if(e.params.data.isNew){
        // append the new option element prenamently:
        $(this).find('[value="'+e.params.data.id+'"]').replaceWith('<option selected value="'+e.params.data.id+'">'+e.params.data.text+'</option>');
        // store the new tag:
        $.ajax({
            // ... 
        });
    }
});

DEMO


[EDIT]
(Small update: see @Alex comment below)

The above will work only if the tag is added with mouse. For tags added by hitting space or comma, use change event.

Then you can filter option with data-select2-tag="true" attribute (new added tag):

$('.select2').select2({
    tags: true,
    tokenSeparators: [",", " "]
}).on("change", function(e) {
    var isNew = $(this).find('[data-select2-tag="true"]');
    if(isNew.length && $.inArray(isNew.val(), $(this).val()) !== -1){
        isNew.replaceWith('<option selected value="'+isNew.val()+'">'+isNew.val()+'</option>');
        $.ajax({
            // ... store tag ...
        });
    }
});

DEMO 2

Upvotes: 47

Tebe
Tebe

Reputation: 3214

Another workaround. Just insert it to the beginning:

           }).on('select2:selecting', function (evt) {

             var stringOriginal = (function (value) {
                // creation of new tag
                if (!_.isString(value)) {
                    return  value.html();
                }
                // picking existing
                return value;
            })(evt.params.args.data.text);
            ........

It relies on underscore.js for checking if it's string or not. You can replace _.isString method with whatever you like.

It uses the fact that when new term is created it's always an object.

Upvotes: 0

Related Questions