Reputation:
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?
$('#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!');
}
});
});
Upvotes: 13
Views: 57955
Reputation: 1
If you've prevented the default behavior of an event using e.preventDefault()
, and you now want to execute your custom action but still allow the default behavior to occur, you can achieve this by using e.stopPropagation()
instead of e.preventDefault()
.
Here's how you can modify your code:
ele.on("select2-selecting", function(e) {
// Execute your custom action here
// If you want to allow the default behavior to occur after your action,
// use e.stopPropagation() instead of e.preventDefault()
e.stopPropagation();
});
By using e.stopPropagation()
, you're not preventing the default behavior of the event, but you're stopping its propagation further up the DOM tree. This means that your custom action will be executed, and then the event will continue its normal flow, potentially triggering any default behavior associated with it.
However, please note that using e.stopPropagation()
might not always be appropriate, especially if there are other event handlers or listeners further up the DOM tree that rely on the event propagation. Make sure to consider the implications of stopping event propagation in your specific scenario.
Upvotes: 0
Reputation: 1
here how I did it for yii2 Select2 integrated into 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.
Upvotes: 0
Reputation: 16297
There is a way to get around this with version4 of the select2 library.
on select2:selecting
we cancel the preTrigger event. Which will stop the select2:select
event. We do our ajax call. 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.
The call
method needs your select2 instance as the context so that the existing listeners are available to call.
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;
}
Upvotes: 10
Reputation: 41671
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:
preventDefault
to make the difference.Both options have their pros and cons, and it's up to you to decide which option you go with.
Pros
Cons
Pros
Cons
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.
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.
Upvotes: 11