Nalin Agrawal Nalin Agrawal - 24 days ago 18
jQuery Question

Show one default option in Autocomplete Search

I have a Jquery autocomplete -

<input type="text" id="contactName" class="form-control input-lg formData textVal" placeholder="Contact Name&#42;"/>


With JQuery code as follows -

$('#contactName').autocomplete({
source: contacts,
minLength: 0,
autoFocus: true,
open: function(event) {},
close: function() {},
focus: function(event,ui) {

},
select: function(event, ui) {
if(ui.item.id == 'create-new-contact'){
//do something to create a new contact
}else{
$('#contactIDVal').val(ui.item.id);
}
}
}).on('focus', function(){$(this).autocomplete("search");});
$("#contactName").autocomplete('instance')._renderMenu = function(ul, items) {
var self = this;
ul.prepend('<li value="create-new-contact">Create New Contact</li>');
$.each( items, function( index, item ) {
self._renderItemData( ul, item );
});
};


What I want is to show 'Create New Contact' option always. Even if the typed text matches with elements in my array or NOT. I am able to achieve the first part, but when the typed text do not match with any items in the array, _renderMenu is not even called. How do I show one default option always whether or not the typed text matches anything in the source array.

In addition to that, The default item that I creating here -

ul.prepend('<li value="create-new-contact">Create New Contact</li>');


is giving me following error when I am taking my mouse over this item -

Uncaught TypeError: Cannot read property 'value' of undefined
at $.(anonymous function).(anonymous function).menufocus (http://code.jquery.com/ui/1.11.4/jquery-ui.js:3012:49)
at HTMLUListElement.handlerProxy (http://code.jquery.com/ui/1.11.4/jquery-ui.js:726:7)
at HTMLUListElement.dispatch (https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js:4:8549)
at HTMLUListElement.r.handle (https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js:4:5252)
at Object.trigger (https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js:4:7650)
at HTMLUListElement.<anonymous> (https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js:4:15517)
at Function.each (https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js:2:2975)
at m.fn.init.each (https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js:2:835)
at m.fn.init.trigger (https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js:4:15493)
at $.(anonymous function).(anonymous function)._trigger (http://code.jquery.com/ui/1.11.4/jquery-ui.js:813:16)


Any ideas how I can achieve this without all this garbage?
Thanks

EDIT -
I solved it with the help of @ADyson

$('#contactName').autocomplete({
source: contacts,
response: function(event, ui){
ui.content.push({id:'create-new-contact', label:'Create New Contact', value:'Create New Contact'});
},
minLength: 0,
autoFocus: true,
open: function(event) {},
close: function() {},
focus: function(event,ui) {

},
select: function(event, ui) {
if(ui.item.id == 'create-new-contact'){
//do some stuff here
}else{
$('#contactIDVal').val(ui.item.id);
}
}
}).on('focus', function(){$(this).autocomplete("search");});

Answer

The simplest solution here is to inject the default value into the returned list of suggestions, then it can always be displayed no matter what the user types. This is much easier than trying to manipulate the generated HTML markup, which you were attempting.

There are two ways of doing this using the autocomplete's API:

1) Creating a custom data source. http://api.jqueryui.com/autocomplete/#option-source - The "source" option can be a function, in which you can do whatever you like, as long as you provide a list of responses back in a callback.

2) Handling the "repsonse" event. http://api.jqueryui.com/autocomplete/#event-response - This gives you access to the list of returned responses just before they are displayed to the user (even if there are no matching responses found, this event will still fire). At this point you can easily add your default item to the array of responses.

Personally of those, for what you want to do I think option 2 is the simplest.