简体   繁体   English

jquery Select2防止在ajax响应中选择

[英]jquery Select2 prevent selecting in ajax response

I want to prevent from adding a category to the Select2 element if it fails creating the row first in my db.如果在我的数据库中首先创建行失败,我想阻止向 Select2 元素添加类别。 The action is not prevented when i call ev.preventDefault();当我调用 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!');
                }
            });
        });

The AJAX request is made asynchronusly, so by the time it has finished the element has already been added. AJAX 请求是异步发出的,因此在它完成时元素已经被添加。 Even though you are calling ev.preventDefault() , it is too late for it to make a difference.即使您正在调用ev.preventDefault() ,也为时已晚,要有所作为。 So this leaves you with two options:所以这给你留下了两个选择:

  1. Make the request synchronusly, which will allow preventDefault to make the difference.同步发出请求,这将允许preventDefault发挥作用。
  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.阻止 UI - 因此在发出请求时,用户可能会看到一个无响应的页面。

  1. Making the request asynchronusly异步发出请求

Pros优点

  • Does not block the UI.不阻塞 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.在发出同步请求时,浏览器停止中继事件的情况并不少见 - 这会让人产生 UI 已锁定且页面无响应的错觉。 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.这在 Web 应用程序中很常见,您可以在许多地方看到它的使用,例如 Twitter 和 Facebook 之类的按钮(请求通常在这些地方工作),以及 Stack Overflow 上的地方。

There is a way to get around this with version4 of the select2 library.有一种方法可以使用 select2 库的 version4 来解决这个问题。

on select2:selecting we cancel the preTrigger event.select2:selecting我们取消了 preTrigger 事件。 Which will stop the select2:select event.这将停止select2:select事件。 We do our ajax call.我们进行 ajax 调用。 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.成功后,我们将退出Select2实例,然后通过在您的 select2 实例上传递覆盖的触发器方法来调用观察者的触发器。

The call method needs your select2 instance as the context so that the existing listeners are available to call. 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;
}

here how I did it for yii2 Select2 integrated into Gridview:在这里,我是如何将 yii2 Select2 集成到 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.它允许使用 select2 和 ajax 异步更新网格中的数据,如果更新出错,则将其返回到先前的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM