I implemented a tagging system where you can choose from existing tags or add new tags. After a new tag has been selected it will persisted using an AJAX call.
For achieving this I use the callback createTag
and the event select2:select
. Because I like to create the tag only when it is selected I do an AJAX call for this if the event select2:select
gets triggered.
The problem is that I need to update the already created option of select2 with the ID I get from persisting my new tag to the database. What's the cleanest solution for this?
Here's what I have:
$('select.tags').select2({
tags: true,
ajax: {
url: '{{ path('tag_auto_complete') }}',
processResults: function (data) {
return {
results: data.items,
pagination: {
more: false
}
};
}
},
createTag: function (tag) {
return {
id: tag.term, // <-- this one should get exchanged after persisting the new tag
text: tag.term,
tag: true
};
}
}).on('select2:select', function (evt) {
if(evt.params.data.tag == false) {
return;
}
$.post('{{ path('tag_crrate_auto_complete') }}', { name: evt.params.data.text }, function( data ) {
// ----> Here I need to update the option created in "createTag" with the ID
option_to_update.value = data.id;
}, "json");
});
New options can be added to a Select2 control programmatically by creating a new Javascript Option object and appending it to the control: var data = { id: 1, text: 'Barn owl' }; var newOption = new Option(data.text, data.id, false, false); $('#mySelect2').append(newOption).trigger('change');
HTML. Create a <select class="select2_el" > element to initialize select2 on page load and create <div id="elements" > container to store <select > element on button click using jQuery AJAX.
Automatic tokenization into tags Select2 supports ability to add choices automatically as the user is typing into the search field. Try typing in the search field below and entering a space or a comma. The separators that should be used when tokenizing can be specified using the tokenSeparators options.
By default, Select2 will attach the dropdown to the end of the body and will absolutely position it to appear above or below the selection container. Select2 will display the dropdown above the container if there is not enough space below the container, but there is enough space above it.
My problem was that I did not add the new tag as an <option>
tag to the native select field.
This is necessary because select2 checks for the values set trough select2.val(values)
if an <option>
tag with this value does exist. If not select2 silently throws the value out of the array and sets the array of values which have a corresponding option tag in the underlying select field.
So this is how it works correct now (for select2 4.0.x):
$('select.tags').select2({
tags: true,
ajax: {
url: '{{ path('tag_auto_complete') }}',
processResults: function (data) {
return {
results: data.items,
pagination: {
more: false
}
};
}
},
createTag: function (tag) {
return {
id: tag.term,
text: tag.term,
tag: true
};
}
}).on('select2:select', function (evt) {
if(evt.params.data.tag == false) {
return;
}
var select2Element = $(this);
$.post('{{ path('tag_crrate_auto_complete') }}', { name: evt.params.data.text }, function( data ) {
// Add HTML option to select field
$('<option value="' + data.id + '">' + data.text + '</option>').appendTo(select2Element);
// Replace the tag name in the current selection with the new persisted ID
var selection = select2Element.val();
var index = selection.indexOf(data.text);
if (index !== -1) {
selection[index] = data.id.toString();
}
select2Element.val(selection).trigger('change');
}, 'json');
});
The minimal AJAX response (JSON format) has to look like this:
[
{'id': '1', 'text': 'foo'},
{'id': '2', 'text': 'bar'},
{'id': '3', 'text': 'baz'}
]
You may add additional data to each result for let's say own rendering of the result list with additional data in it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With