jquery Select2 防止在 ajax 响应中选择

Posted

技术标签:

【中文标题】jquery Select2 防止在 ajax 响应中选择【英文标题】:jquery Select2 prevent selecting in ajax response 【发布时间】:2014-12-29 13:40:08 【问题描述】:

如果在我的数据库中首先创建行失败,我想阻止向 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!');
                
            );
        );

【问题讨论】:

【参考方案1】:

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

    同步发出请求,这将使preventDefault 有所作为。 异步发出请求,如果失败则手动删除元素。

这两种选择各有利弊,您可以自行决定选择哪一种。


    同步发出请求

优点

如果请求失败,则永远不会添加该值。 在不能经常添加元素的情况下效果很好。

缺点

阻止 UI - 因此用户在发出请求时可能会看到无响应的页面。
    异步发出请求

优点

不阻塞用户界面。 在通常可以添加元素的情况下效果很好。

缺点

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

这里需要考虑的重要一点是这两个选项的用户体验。在发出同步请求时,浏览器停止中继事件的情况并不少见——这会产生 UI 已锁定且页面已无响应的错觉。这样做的好处是确保在不允许的情况下该值永远不会出现。但是,如果用户通常可以添加元素,那么它也有使最常见的用例复杂化的缺点。

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

【讨论】:

【参考方案2】:

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

select2:selecting 上,我们取消了 preTrigger 事件。这将停止select2:select 事件。我们进行 ajax 调用。成功后,我们将退出 Select2 实例,然后调用 Observer 的触发器,通过在您的 select2 实例上传递覆盖的触发器方法。

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;

【讨论】:

【参考方案3】:

这里我是如何将 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;
    ",
    ],

它允许使用 select2 和 ajax 异步更新网格中的数据,如果更新出现错误,则将其返回到以前的值。

【讨论】:

以上是关于jquery Select2 防止在 ajax 响应中选择的主要内容,如果未能解决你的问题,请参考以下文章

ajax调用HTML内容更改后select2 jquery插件不起作用

jQuery.map() 解析 select2 ajax 调用的结果

将参数传递给 jQuery 的 select2 ajax 调用

使用带有标签的select2 jquery插件:true,您如何防止选择出现在已选择的下拉列表中?

如何使用配置了ajax搜索的select2 jquery插件实现选择所有功能。?

使用 Ajax 的 jQuery Select2 插件