【问题标题】:jquery Select2 prevent selecting in ajax responsejquery Select2 防止在 ajax 响应中选择
【发布时间】: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!');
                }
            });
        });

【问题讨论】:

    标签: javascript jquery ajax jquery-select2


    【解决方案1】:

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

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

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


    1. 同步发出请求

    优点

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

    缺点

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

    1. 异步发出请求

    优点

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

    缺点

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

    这里需要考虑的重要一点是这两个选项的用户体验。在发出同步请求时,浏览器停止中继事件的情况并不少见——这会产生 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 异步更新网格中的数据,如果更新出现错误,则将其返回到以前的值。

        【讨论】:

          猜你喜欢
          • 2013-06-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-12-19
          • 1970-01-01
          • 2020-02-25
          相关资源
          最近更新 更多