Hey there!
Chosen is a jQuery Plugin, which gives some beautifully looking multiple selects in your form. The select can have some options populated, and the user can select one or multiple of them.
Recently, while using this plugin, I wanted to allow the user to add his own values to the list dynamically. Currently, in case the value is not there in the result, a ‘No result found’ message is shown.
I googled for a solution, and got some tweaks. This is what I did to achieve.
In the source code (chosen.jquery.js), I made a slight modification to the keyup_checker function.
1. Go to case 13 option in the switch block. (13 is the keycode for ‘Enter’)
if (this.results_showing) { return this.result_select(evt); }
What it currently does is, it checks whether there is a result bound to the user input, if so, it returns it. If not, it does nothing.
So, we need to handle when this condition fails, i.e. when the user inputs a value, and it does not match any result.
2. This is the code to handle it.
$(this.form_field).append('<option>' + $(evt.target).val() + '</option>'); $(this.form_field).trigger('chosen:updated'); this.result_highlight = this.search_results.find('li.active-result').last(); return this.result_select(evt);
$(evt.target).val() has the user input value. You add it to the list. Then do a chosen:update trigger to update the list.
According to the docs(link),
If you need to update the options in your select field and want Chosen to pick up the changes, you’ll need to trigger the “chosen:updated” event on the field. Chosen will re-build itself based on the updated content.
Finally, you add it to the results and return it.
Your final code in case 13 looks like this:
case 13: evt.preventDefault(); if (this.results_showing) { if (!this.is_multiple || this.result_highlight) { return this.result_select(evt); } $(this.form_field).append('<option>' + $(evt.target).val() + '</option>'); $(this.form_field).trigger('chosen:updated'); this.result_highlight = this.search_results.find('li.active-result').last(); return this.result_select(evt); } break;
You can also modify the ‘No result text’ text to include your added functionality.
$("#your-element").chosen( {no_results_text: "No result found. Press enter to add "} );
That’s all about it! 🙂
Do leave a comment if you have better solution.
Cheers,
Aishwarya 🙂
Thank you 🙂
LikeLike
Hello, thank you for your idea. Please, could you share thhe final program file *.js for direct downloading?
And I have a question. I need exactly this, i.e. to add a record if is not added yet. BUT. I need to add new content of one node in Drupal. So, no just add word, but add the whole node (for example I am adding car. In the list you see just name and types of cars /AUDI TT, SKODA SUPERB, CITROEN C6 et/, but in details of that nodes are pictures, characters, description, version etc… So if I will add new car for example “BMW xyz”, I also need to be redirected to form for add all the information to that node/content; not only the name of car).
I am not good developer, but I have particular requirements for my pages..
Thank you!
LikeLike
Hi Kejmil,
In my post above, look for the code snippet having case 13: (it is the last but one code).
Find case 13: in your chosen.jquery.js file, and replace it with the code snippet I have provided.
If you need to redirect the user to a form to add other details of the car, before the $(this.form_field).trigger(‘chosen:updated’); statement(can be found in the same code block as above), you need to redirect the user to your form page.
Hope this helps. Let me know if you have any confusions.
LikeLike
and please, I have change the code, but i dont know how to trigger the “chosen:updated”. I dont understand the process. Where to go and how to trigger it? what to set? how to update?
LikeLike
Please check case 13: in the code snippet I have given.
chosen:updated has already been triggered.
Check this line: $(this.form_field).trigger(‘chosen:updated’);
LikeLike
Hi, I desire to subscribe for this web site to obtain latest updates, therefore where can i do it please assist. bdekfdcggcbd
LikeLike
Hi John,
You can subscribe by entering your email address at the ‘Follow blog via Email’ on the right side. Thanks! 🙂
LikeLike
I got this website from my friend who told me concerning this web site and at the moment this time I am visiting this web page and reading very informative content here. kkdeabfbbbaf
LikeLike
Glad you liked it!
LikeLike
Hey Aishwarya, I’m so glad you posted this… I was just looking for something just like this and I’m so happy you spared me the time of trying to figure it out. All my best!
Tyle
LikeLike
Hey Tyler(Gautam),
Am glad you found it useful! Cheers! 🙂
LikeLike
I have fun with, lead to I found just what I used to be looking
for. You have ended my 4 day long hunt! God Bless you man. Have
a nice day. Bye
LikeLike
Hello there, just became alert to your blog through Google,
and found that it is truly informative. I’m gonna watch out for brussels.
I’ll be grateful if you continue this in future. Many people
will be benefited from your writing. Cheers!
LikeLike
I wanted to do the same & ran into your post. I needed to add some application logic besides just adding the value. So I decided to pass a callback function & execute it.
I added these two lines in AbstractChosen.prototype.set_default_values to get the callback & a value to know if the add element functionailty is needed.
this.add_no_result_not_found = this.options.add_no_result_not_found || false;
/*
(If we want the add functionality)
*/
this.no_result_found_callback = this.options.no_result_found_callback || false;
/*
(The callback )
*/
//This is my case 13 block inside keyup_checker
if (this.results_showing) {
if (this.result_highlight) {
return this.result_select(evt);
}
if (this.add_no_result_not_found){
if (typeof(this.no_result_found_callback) == ‘function’){
this.no_result_found_callback($(evt.target).val());
return this.result_select(evt);
}
}
}
The value is added inside my callback alongwith my application logic.
My chosen invocation looks like this,
if(addNotFound && notFoundCallback){
options[‘add_no_result_not_found’] = addNotFound;
options[‘no_result_found_callback’] = notFoundCallback;
options[‘no_results_text’] = “Enter to add the option”;
}
select.chosen(options);
Hope this help 🙂
LikeLike
Thanks for adding in! 🙂
LikeLike
Hey Aishwarya, I am so glad you posted this…I am just looking for something like this.
Thanks 🙂
LikeLike
thanks!
this is what I was looking for.
LikeLike
Hey Awesome stuff!
I made it work but it doesn’t select the new entry automatically but it shows in the drop menu. Have you encountered the same issue?
Regards
LikeLike
I have found the solution you just need to add selected to the tag so instead of this:
$(this.form_field).append(” + $(evt.target).val() + ”);
is this:
$(this.form_field).append(” + $(evt.target).val() + ”);
This will add automatically to the list the new items.
Again, awesome stuff!
LikeLike
Hi Albert!
Thanks for your comments.
The new entry would automatically show up according to the code given above.
Please check for the following line which performs the operation:
return this.result_select(evt);
Also, you have mentioned the same line of code in your solution comment, did you mean something else?
I have found the solution you just need to add selected to the tag so instead of this:
$(this.form_field).append(” + $(evt.target).val() + ”);
is this:
$(this.form_field).append(” + $(evt.target).val() + ”);
LikeLike
Have you seen the “semi-official” option adding implementation; https://github.com/harvesthq/chosen/pull/166
Side note, I’m the developer of the functionality, so I’m biased, but besides that I’m also a developer of the Chosen plugin itself.
LikeLike
This is great! Has it been merged yet?
LikeLike
i don’t know if your website messed up the formatting of your code when you copy and pasted it, but i had to make some changes to get mine to work.
the code above looked like:
.lasteturn this.result_select(evt);
}
i needed to end the last(); and fix the “return” part. changes seen below. your code also seemed to work only for single-selects, so i commented out the part that prevented it for working for multi-selects (which i needed too)
case 13:
evt.preventDefault();
if (this.results_showing) {
// if (this.is_multiple || this.result_highlight) {
if (this.result_highlight) {
return this.result_select(evt);
}
$(this.form_field).append(” + $(evt.target).val() + ”);
$(this.form_field).trigger(‘chosen:updated’);
this.result_highlight = this.search_results.find(‘li.active-result’).last();
return this.result_select(evt);
}
LikeLike
Hello,
The copy pasting from the above post is working fine for me.
LikeLike
Thank you for sharing useful knowledge.
Please help me for following issues….
this is in step 2 of your code
this.result_highlight = this.search_results.find(‘li.active-result’).lastrn this.result_select(evt);
and this is in step 3
this.result_highlight = this.search_results.find(‘li.active-result’).lasteturn this.result_select(evt);
i’m confusing @lastrn of step 2 and @lasteturn of step 3.
Can you please explain it, If you don’t mind
LikeLike
Hello Dip,
It was an issue with my website theme. Fixed now 🙂
LikeLike
Thank You very much for your valuable response…..
But still it is not working for me…..
LikeLike
Thanks for the useful code! but I have an issue: the javascript array is (the one bonded to ng-options) is not updating. only the HTML is. how can I fix this?
LikeLike
Am I doing something wrong – I can’t get this to add the term to the taxonomy when I save the form.
I understand probably because I’m using a select list, which doesn’t allow adding taxonomy terms, but Chosen doesn’t work with Autocomplete Tagging widget (which does allow adding tags).
Any help out for a noob?
LikeLike
Great.. you made my day .. #Perfect trick I was looking for this solution.
Need a help for one more problem . I have string (test1,test2,test3,test4) when users hits enter key i want separate the string and update a chosen listz with test1 and test2 and test3 and test4 as a 4 options selected …
Below is my code
case 13:
//if (a.preventDefault(), this.results_showing)
// return this.result_select(a);
//break;
a.preventDefault();
if (this.results_showing) {
if (!this.is_multiple || this.result_highlight) {
return this.result_select(a);
}
if($(a.target).val().indexOf(‘,’) !== -1) {
// console.log(“You are in”);
// console.log($(a.target).val());
var source =$(a.target).val().split(‘,’);
//console.log(source);
$.each(source, function (i) {
console.log(source[i]);
$(this.form_field).append(” + source[i] + ”);
$(this.form_field).trigger(‘chosen:updated’);
//this.result_highlight = this.search_results.find(‘.active-result’).last();
//return this.result_select(a);
});
} else {
$(this.form_field).append(” + $(a.target).val() + ”);
$(this.form_field).trigger(‘chosen:updated’);
this.result_highlight = this.search_results.find(‘.active-result’).last();
return this.result_select(a);
}
}
break;
failed to update the list
LikeLike
finally done with this 🙂
case 13:
//if (a.preventDefault(), this.results_showing)
// return this.result_select(a);
//break;
a.preventDefault();
if (this.results_showing) {
if (!this.is_multiple || this.result_highlight) {
return this.result_select(a);
}
if($(a.target).val().indexOf(‘,’) !== -1) {
var source =$(a.target).val().split(‘,’);
var inputId=$(this.form_field);
inputId=inputId[0][‘id’];
$.each(source, function (i) {
$(“#”+inputId).append(” + source[i] + ”);
$(“#”+inputId).trigger(‘chosen:updated’);
});
} else {
$(this.form_field).append(” + $(a.target).val() + ”);
$(this.form_field).trigger(‘chosen:updated’);
}
this.result_highlight = this.search_results.find(‘.active-result’).last();
return this.result_select(a);}
break;
LikeLike
Hi in your code
this.result_highlight = this.search_results.find(‘li.active-result’).lasteturn this.result_select(evt);
this will get an error in javascript. The error is “expecting new line or semicolon”. Any idea how to fix this.
LikeLike
Ok I have fix the problem there is a typo in your code
In your code
this.result_highlight = this.search_results.find(‘li.active-result’).lasteturn this.result_select(evt);
I change it to
this.result_highlight = this.search_results.find(‘.active-result’).last();
return this.result_select(evt);
LikeLike
Please can you show a demo of your code i’m trying to implement the same thing as you stated above but it is just disrupting the chosen format and making it a simple multiselect list,
P.S. – I am trying it for a multiple select list ,
Just a demo or a link where this is working would do 🙂 !
LikeLike
That pull request mentioned above is still under discussion, so I have forked chosen-rails in order to make use of its functionality within sprockets: https://github.com/tylergannon/chosen-rails
LikeLike
Thanks, it helps me.
LikeLike
Correct this line
this.result_highlight = this.search_results.find(‘li.active-result’).lasteturn this.result_select(evt);
to
this.result_highlight = this.search_results.find(‘li.active-result’).last();
return this.result_select(evt);
LikeLike
Superb work !!! thank you a lot.It save my time….
LikeLike
Great Stuff !! I wanted to use this with a multi-select however i did notice that the code was wrong for the case 13 it should be this:
case 13:
evt.preventDefault();
if (this.results_showing) {
if (!this.is_multiple || this.result_highlight) {
return this.result_select(evt);
}
$(this.form_field).append(” + $(evt.target).val() + ”);
$(this.form_field).trigger(‘chosen:updated’);
this.result_highlight = this.search_results.find(‘li.active-result’).last();
return this.result_select(evt);
}
break;
LikeLike
How to bind that “New value” using angular js
LikeLike
thanks buddy it saved my time 🙂
LikeLike
i am using this plugin on my application, but i want add new option functionality only on one place not any other places, after this change, its apply to all over the application please suggest me
LikeLike