Javascript jquery Select2防止在ajax响应中选择
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26705098/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
jquery Select2 prevent selecting in ajax response
提问by Michalis Daniilakis
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?
如果在我的数据库中首先创建行失败,我想阻止向 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!');
}
});
});
采纳答案by Kevin Brown
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:
AJAX 请求是异步发出的,因此在它完成时元素已经被添加。即使你在打电话ev.preventDefault(),也为时已晚,要有所作为。所以这给你留下了两个选择:
- Make the request synchronusly, which will allow
preventDefaultto make the difference. - Make the request asynchronusly, and manually remove the element if it fails.
- 同步发出请求,这将
preventDefault有所作为。 - 异步发出请求,如果失败则手动删除该元素。
Both options have their pros and cons, and it's up to you to decide which option you go with.
两种选择都有其优点和缺点,由您决定选择哪个选项。
- 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 - 因此在发出请求时,用户可能会看到一个无响应的页面。
- Making the request asynchronusly
- 异步发出请求
Pros
优点
- Does not block the UI.
- Works well in cases where elements typically can be added.
- 不阻塞 UI。
- 在通常可以添加元素的情况下效果很好。
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.
这里需要重点考虑的是这两个选项的用户体验。在发出同步请求时,浏览器停止中继事件的情况并不少见 - 这会让人产生 UI 已锁定且页面无响应的错觉。这样做的好处是可以确保值在不允许的情况下永远不会出现。但是,如果用户通常可以添加元素,那么它也有使最常见用例复杂化的缺点。
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 上的地方。
回答by brenjt
There is a way to get around this with version4 of the select2 library.
有一种方法可以使用 select2 库的 version4 来解决这个问题。
on select2:selectingwe cancel the preTrigger event. Which will stop the select2:selectevent. We do our ajax call. On success we then get out Select2instance then call the trigger of the Observer that way it by passes overwritten trigger method on your select2 instance.
在select2:selecting我们取消预触发事件。这将停止select2:select事件。我们进行 ajax 调用。成功后,我们将退出Select2实例,然后通过在您的 select2 实例上传递覆盖的触发器方法来调用观察者的触发器。
The callmethod 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;
}

