jquery Select2 prevent selecting in ajax response

懵懂的女人 提交于 2021-02-07 05:46:47

问题


I want to prevent from adding a category to the Select2 element if it fails creating the row first in my db. The action is not prevented when i call ev.preventDefault(); Nothing happens.. what is wrong?

    $('#sel2').select2({
            placeholder: 'Enter categories',
            minimumInputLength: 3,
            multiple: true,
            ajax: {
                url: 'async/get_categories.php',
                dataType: 'json',
                quietMillis: 250,
                data: function (term, page) {
                    return {
                        q: term,
                    };
                },
                results: function (data, page) {
                    return {
                        results: data.items 
                    };
                },
                cache: true
            },
            formatResult: format,
            formatSelection: format
        }).on('select2-selecting', function(e) {
            console.log(e);
            if (e.val == 4) {
                // if category id equals 4
                // do not add this category to select 2
                // e.preventDefault();
                // the above works just fine and its just for testing
            }

            // Is something wrong here?
            var ev = e;

            $.ajax({
                type: 'POST',
                url: 'async/create_profile_category.php',
                data: {
                    profile_id: '1', 
                    category_id: ev.val
                },
                success: function(response) {
                    console.log(response);
                    if (response.error === false) {
                        // category assigned successfully
                    } else {
                        // failed to assign category
                        // so i want now to prevent from adding to select2
                        console.log('should not add this category');
                        ev.preventDefault();
                        // the above is not working
                    }
                },
                error: function() {
                    alert('Failed to assign category!');
                }
            });
        });

回答1:


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.




回答2:


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;
}


来源:https://stackoverflow.com/questions/26705098/jquery-select2-prevent-selecting-in-ajax-response

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!