jquery Select2 prevent selecting in ajax response jquery Select2 prevent selecting in ajax response ajax ajax

jquery Select2 prevent selecting in ajax response


The AJAX request is made asynchronusly, so by the time it has finished the element has already been added. Even though you are calling ev.preventDefault(), it is too late for it to make a difference. So this leaves you with two options:

  1. Make the request synchronusly, which will allow preventDefault to make the difference.
  2. Make the request asynchronusly, and manually remove the element if it fails.

Both options have their pros and cons, and it's up to you to decide which option you go with.


  1. Making the request synchronusly

Pros

  • The value will never be added if the request fails.
  • Works well in cases where the element cannot be added quite often.

Cons

  • Blocks the UI - So the user is potentially left with an unresponsive page while the request is made.

  1. Making the request asynchronusly

Pros

  • Does not block the UI.
  • Works well in cases where elements typically can be added.

Cons

  • The value will always show up for the user, even if it fails later.
  • You must manually unset the new option.

What's important to consider here is the user experience of both options. When making synchronus requests, it's not uncommon for the browser to stop relaying events - which gives the illusion that the UI has locked up and the page has gone unresponsive. This has the benefit of ensuring that the value never shows up if it isn't allowed. But if users typically can add the elements, it also has the downside of complicating the most common use case.

If users can usually add elements, then it is a better experience to add the element while the request is being made, and then notifying the user later (while removing the element) if there was an issue. This is very common is web applications, and you can see it being used in many places, such as the Twitter and Facebook like buttons (where requests usually work), as well as places on Stack Overflow.


There is a way to get around this with version4 of the select2 library.

on select2:selecting we cancel the preTrigger event. Which will stop the select2:select event. We do our ajax call. On success we then get out Select2 instance then call the trigger of the Observer that way it by passes overwritten trigger method on your select2 instance.

The call method needs your select2 instance as the context so that the existing listeners are available to call.

var sel = $('#sel');sel.select2(config);sel.on('select2:selecting', onSelecting);function onSelecting(event){    $.ajax({        type: 'POST',        url: 'async/create_profile_category.php',        data: {            profile_id: '1',             category_id: event.params.args.data.id        },        success: function(event, response) {            console.log(response);            if (response.error === false) {                // category assigned successfully                // get select2 instance                var Select2 = $users.data('select2');                // remove prevented flag                delete event.params.args.prevented;                // Call trigger on the observer with select2 instance as context                Select2.constructor.__super__.trigger.call(Select2, 'select', event.params.args);            } else {                // failed to assign category                // so i want now to prevent from adding to select2                console.log('should not add this category');            }        }.bind(null, event),        error: function() {            alert('Failed to assign category!');        }    });    event.preventDefault();    return false;}


here how I did it for yii2 Select2 integrated into Gridview:

    'pluginEvents' => [    'select2:selecting' => "    function(event)     {         var select2 = $('#types-" . $model->id . "');        select2.select2('close');        $.post('update',{id: " . $model->id . ", type_id: event.params.args.data.id})        .done (function(response)         {            select2.val(event.params.args.data.id);            select2.trigger('change');        })         .fail(function(response)         {             krajeeDialog.alert('Error on update:'+response.responseText);        });        event.preventDefault();        return false;    }",    ],

it allows to asynchoronous update data in the grid using select2 and ajax and return it to previous value if there was an error on updating.