jquery Select2阻止在ajax响应中进行选择

Mic*_*kis 5 javascript ajax jquery jquery-select2

如果在我的数据库中首先创建行失败,我想阻止向Select2元素添加类别.当我调用ev.preventDefault()时,不会阻止该操作; 什么都没发生..有什么不对?

    $('#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!');
                }
            });
        });
Run Code Online (Sandbox Code Playgroud)

Kev*_*own 7

AJAX请求是异步进行的,所以当它完成时,元素已经被添加.即使你在打电话ev.preventDefault(),也不能有所作为.所以这给你留下了两个选择:

  1. 同步地发出请求,这将preventDefault产生差异.
  2. 异步发出请求,如果失败则手动删除该元素.

这两种选择都有其优点和缺点,由您决定使用哪个选项.


  1. 同步发出请求

优点

  • 如果请求失败,则永远不会添加该值.
  • 适用于无法经常添加元素的情况.

缺点

  • 阻止UI - 因此,在发出请求时,用户可能会留下无响应的页面.

  1. 异步地发出请求

优点

  • 不阻止UI.
  • 适用于通常可以添加元素的情况.

缺点

  • 即使以后失败,该值也将始终显示给用户.
  • 您必须手动取消设置新选项.

这里要考虑的重要因素是两种选择的用户体验.在进行同步请求时,浏览器停止中继事件的情况并不少见 - 这会让人觉得UI已经锁定并且页面没有响应.这有利于确保在不允许的情况下价值永远不会出现.但是,如果用户通常可以添加元素,那么它也有使最常见用例复杂化的缺点.

如果用户通常可以添加元素,那么在发出请求时添加元素是一种更好的体验,然后在出现问题时稍后通知用户(同时删除元素).这是非常常见的Web应用程序,您可以看到它在许多地方使用,例如Twitter和Facebook之类的按钮(请求通常在哪里工作),以及Stack Overflow上的位置.


bre*_*njt 6

有一种方法可以使用select2库的version4来解决这个问题.

select2:selecting我们取消预触发事件.哪个会阻止这个select2:select事件.我们做ajax电话.成功之后,我们将Select2实例调出,然后通过在select2实例上传递覆盖的触发器方法来调用Observer的触发器.

call方法需要您的select2实例作为上下文,以便可以调用现有的侦听器.

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;
}
Run Code Online (Sandbox Code Playgroud)