Using jQuery UI Autocomplete with Hidden ID's

coldfusion

The new autocomplete widget in jQuery UI 1.8 is a nice addition. While it works great for basic purposes working with ID / value pairs is not so nice out of the box.

I wanted to use the autocomplete widget to allow someone to select an employee by typing in an employee name into the text box, but I want the form to post the ID of the employee, not the employee name.

First you need to setup your server side search script, I'm using ColdFusion here:

<cfparam name="url.term" default="">
<cfset emp = empDAO.searchByName(url.term)>
<cfset result = ArrayNew(1)>
<cfoutput query="emp">
	<cfset s = StructNew()>
	<cfset s["label"] = emp.FullName>
	<cfset s["value"] = emp.EE_ID>
	<cfset ArrayAppend(result, s)>
</cfoutput>
<cfset json = SerializeJSON(result)>
<cfcontent reset="true" type="application/json"><cfoutput>#json#</cfoutput><cfabort>

The jQuery UI autocomplete widget sends a variable in the query string called term which contains the text the user has typed in. You need to return an array of objects in JSON. For example, your output might look like this:

[{label:"Pete Freitag", value:1}, {label:"Pete Doe", value:2}]

Now the HTML code I am using in the form simply looks like this:

<input type="text" name="EmployeeID" value="" class="employeeAutocomplete" />

Next I need to write some jQuery JavaScript that applies the autocomplete widget to any input tag with the employeeAutocomplete, this code would go in your $(document).ready() event handler:

$('input.employeeAutocompete').autocomplete({source:'employee-search-json.cfm'});

Now this works well up to this point, but when I select an item it put's the employee ID in the text box. From the user perspective this doesn't make any sense. What I want is for the employee's name to be put in the text box, and have a hidden field containing the employee ID passed in the form.

So to accomplish that I need to do a bit more JavaScript, I'm going to do the following:

  1. Change the name on the existing input field to whatever it was plus _autocomplete_label
  2. Create a hidden input field with a name attribute value of the original input element (this will contain my ID value).
  3. Create a custom select event handler for the given jQuery UI autocomplete instance.

So here's my new code:

$('input.employeeAutocomplete').each(function() {
	var autoCompelteElement = this;
	var formElementName = $(this).attr('name');
	var hiddenElementID  = formElementName + '_autocomplete_hidden';
	/* change name of orig input */
	$(this).attr('name', formElementName + '_autocomplete_label');
	/* create new hidden input with name of orig input */
	$(this).after("<input type=\"hidden\" name=\"" + formElementName + "\" id=\"" + hiddenElementID + "\" />");
	$(this).autocomplete({source:'employee-search-json.cfm', 
		select: function(event, ui) {
			var selectedObj = ui.item;
			$(autoCompelteElement).val(selectedObj.label);
			$('#'+hiddenElementID).val(selectedObj.value);
			return false;
		}
	});
});

Now when I submit the form the value of the EmployeeID field will be an employee ID, and the text box will simply show the employee name.

Would be cool if this widget supported an option to do what I just did, but it only takes a few additional lines of code to accomplish.



Related Entries

8 people found this page useful, what do you think?

 Download FuseGuard WAF for ColdFusion

Trackbacks

Trackback Address: 756/29E2A4759B0FD14E123AA7DDEDAEE038

Comments

On 07/14/2010 at 2:13:31 PM UTC Mike wrote:
1
Unless I am not understanding what you are after, the AutoSuggest widget already provides this functionality. Check out

http://www.coldfusionjedi.com/index.cfm/2010/4/12/Playing-with-jQuery-UIs-Autocomplete-Control

On 07/19/2010 at 10:41:39 AM UTC Pete Freitag wrote:
2
@Mike Ray's code example there still has javascript to set the hidden ID, he's not using anything builtin to do that. We are both using the select event to do that, the main difference is that my code creates the hidden form field dynamically, Ray's code has it in the HTML to start with.

On 07/19/2010 at 8:27:06 PM UTC Brian wrote:
3
Pete - be aware that using jQuery 1.4 you need to return valid JSON which means keys are quoted too:

[{"label":"Pete Freitag", "value":1}, {"label":"Pete Doe", "value":2}]

It's possible UI is using getAJAX and then eval'ing it but jQuery 1.4 core has already switched to requiring strict JSON for requests like getJSON().

On 08/12/2010 at 8:50:38 PM UTC Jonathan wrote:
4
Hi Pete,

Thank you very much for this tutorial. It really helped me with the new ui-autocomplete !

http://stackoverflow.com/questions/3446297/posting-value-to-server-using-jquery-ui-autocomplete-and-jeditable

Cheers mate

On 08/26/2010 at 8:30:30 PM UTC Alan McCollough wrote:
5
This Was Awesome! Thank you for solving this puzzle. I spent a morning trying to grasp why the jQuery UI autocomplete was not doing what seemed obvious (to me at least), then found your excellent post. You've saved me a handful of hair.

On 08/27/2010 at 8:21:28 PM UTC Alan McCollough wrote:
6
Got a question. I've used your autocompleter workaround, and it's fantastic for filling out a new form.

Got any suggestions on how to deal with laoding the fields with existing data, as when editing an existing entry?

On 09/03/2010 at 3:34:45 PM UTC Alan McCollough wrote:
7
fwiw, I betcha you meant the spelling of "autoCompelteElement" to be "autoCompleteElement". Still works though, and again let me thank you for a very useful component!

Okay, I'll answer my own question. It was pretty obvious, really. if field name is "foo" and it should preload with a value of "fflintstone" and label of "Flintstone, Fred", this would work for pre-populating those values.

$("input[name=foo_autocomplete_label]").val("Flintstone, Fred"); $("input[name=foo]").val("fflintstone");

On 09/09/2010 at 4:05:58 AM UTC Keith wrote:
8
I'm having an issue using this method for some strange reason. When I have more than one item in the list and I hit my down arrow key on the keyboard to sift through the options, the value (ID) is displayed in the textbox as I scroll through the items. What method is doing this?

On 10/22/2010 at 2:19:37 PM UTC Reguram wrote:
9
Visit www.metads.com. The same script is implemented there.

On 11/15/2010 at 1:57:35 PM UTC Nikhil wrote:
10
Excellent article! Just a suggestion : One could use $(this).data("eid",selectedObj.value) to avoid using a hidden field! :)

On 11/16/2010 at 5:43:41 PM UTC Rafi B. wrote:
11
I found a glitch when you focus on the input and delete the value with backspace, the select event won't fire obviously, but the change event will. So you should add this event:

change: function (event, ui) { if ( ! this.value) { $('#'+hiddenElementID).val('); } },

On 12/10/2010 at 11:39:47 PM UTC Travis wrote:
12
I'm also having the same issue as Keith in comment #8 above. Can't figure out why using arrow keys displays the ID numbers and not the correct letters.

On 12/20/2010 at 4:39:19 AM UTC Bong wrote:
13
using keyboard arrow keys to navigate the options, to forced-display 'label' instead of 'value', try adding this:

focus: function( event, ui ) { $(this).val( ui.item.label ); return false; },

On 02/21/2011 at 12:23:22 PM UTC Pardeep wrote:
14
Do you prefer jquery or prototype for js and ajax functionality? If so, why? Ruby on Rails crowd favor Prototype, I don't have enough experience in either.

On 05/02/2011 at 3:18:06 AM UTC Jacob wrote:
15
Just wanted to say thanks for this - it helped get my head around how to store the ID of the select box, rather than the value.

I ended up just adding a hidden field to the form, and updating the val() of that field with the ID data - works a treat!!

On 05/14/2011 at 7:33:48 PM UTC Kaspar Kappstein wrote:
16
Just to let you know, i found an easyest workaround, but haven't tested it's side effects, but simply, after the success: function(event,ui) {

//do this: event.preventDefault(); }

it worked for me and it doesn't change the value of the text field. I've to save id somwhere to further submit, but that's ok right now.

On 06/09/2011 at 12:58:01 PM UTC Premik wrote:
17
Thanks Kaspar. This workaround worked for me. I guess you ment "select" event, not "success".

$(...).autocomplete({... select : function(event, ui{

event.preventDefault(); $(this).val(ui.item.label); $(this).data("hiddenValue", ui.item.value); }; }

On 06/30/2011 at 12:41:38 PM UTC Andrew wrote:
18
Great tips, both in the tutorial and the comments. jQueryUI Autocompleter working much much better after implementing some of these.

On 07/11/2011 at 8:13:02 PM UTC RET wrote:
19
Kaspar and Premik - thanks for the preventDefault tip, that solves my problem.

I'm using autocomplete to display "CITY, STATE, ZIP", in my city field (to disambiguate city names), and auto-populating all three fields with their appropriate elements. Works a treat.

On 07/18/2011 at 8:19:44 PM UTC Ben wrote:
20
Ufff, incredible.., thanks very much!!!

On 08/05/2011 at 3:32:27 PM UTC Craig wrote:
21
I am using a hidden field to accomplish the same task but have noticed that if you press the back button after submitting the form the hidden value is still set but the autocomplete input is not not. How can you reset the hidden field or set the autocomplete to the current value?

On 09/23/2011 at 2:27:29 AM UTC Kit wrote:
22
Thanks! You just saved the day! :)

On 09/25/2011 at 2:56:40 PM UTC Jon wrote:
23
Craig, I had the same question, after studying the jquery ui doc I found that you can set the focus event like this:

focus: function() { $('#input_you_want_to_reset').val('); }

On 10/19/2011 at 2:29:19 PM UTC Bianchi wrote:
24
You can do that:

focus: function() { $('#input_you_want_to_reset').val('ui.item.label'); }

or if you just doesn't want a return

focus: function() { return false; }

On 11/20/2011 at 6:32:57 AM UTC Mano wrote:
25
Thx ! Exactly what i was trying to do ;)

On 01/06/2012 at 5:51:59 PM UTC MichaelG wrote:
26
When using this jQuery snippet in PHP, valid PHP form element names which use square brackets will fail. For example, foo[bar] is an invalid id in HTML and for jQuery. Such an id either must be escaped or the code altered as below. Otherwise, the cloned form element's value is not set since jQuery can't find the element by id anymore.

I simply changed the snippet as such so the new element's id is not the same as the old element's name:

var formElementName = $(this).attr('name'); ++var formElementId = $(this).attr('id'); --var hiddenElementID = formElementName + '_autocomplete_hidden'; ++var hiddenElementID = formElementId + '_autocomplete_hidden'; /* change name of orig input */

On 01/25/2012 at 4:18:37 PM UTC hamzah wrote:
27
this ok, but missing something. when the autocomplete come out, press arrow down /up using your keyboard. then, it will pass the id on the textbox (before i press enter). i try make the textbox color to white when autocomplete open.. but i still can see it when i highlight the txtbox. any good suggestion?

On 02/09/2012 at 7:18:51 AM UTC John wrote:
28
What if I have multiple selection enabled using autocomplete the trouble is if user deletes the selection I need to be able to delete the id associated too

On 05/03/2012 at 7:26:07 AM UTC CList wrote:
29
To fix the problem with the id numbers showing in the list...

There's nothing to prevent you from adding additional properties to the "item" at the time you retrieve the data, and then using those properties in the "select: function()". I.e. you aren't limited to simply the "label" and "value" being used by the standard autocomplete. I suggest the following:

In the "source" we use ajax to get the data, note that Value and Label are BOTH mapped to the "text" field in the result, and a new property, called "id" is mapped to the id value!

source: function (request, response) { $.ajax({ url: "/Customer/Lookup", type: "POST", dataType: "json", data: { searchText: request.term, maxResults: 25 }, success: function (data) { response($.map(data, function (item) { return { label: item.text, value: item.text, id: item.id } })) } }) },

...Now in select: we use the "id" property to set the value of the hidden field, and we never have to worry about the vanilla auto-complete functionality...

select: function (event, ui) { var selectedObj = ui.item; $(autoCompelteElement).val(selectedObj.label); $('#'+hiddenElementID).val(selectedObj.id); }

On 05/23/2012 at 11:13:44 AM UTC dee wrote:
30
Thanks for this. helped immensely.

On 06/18/2012 at 9:57:28 AM UTC draupadi wrote:
31
Maybe not very fancy, but working: in my case the page is reloaded by location.href, so I don't need the text inside the textboy anymore. So i simply set the textcolor to the background color: select: function(event,ui) { $("<selector>").css({'color':'white'}); ...

On 08/05/2012 at 3:22:29 AM UTC Nabu wrote:
32
weak solution. select event shot when user press enter button, but not while he is pressing an arrow.

I'm extending source array with one field: [label:Pete, value:Pete, dbid:1] And I can get this field form ui.item.dbid.

On 11/23/2012 at 4:09:41 AM UTC phifi wrote:
33
There is a Bug if u use this Script in "ChildTables" where the inputs are generated with id's and name's like this:

<input id="Foo_0__SomePropertyName" name="Foo[0]SomePropertyName">

u should generate the id of the hidden field like this to avoid that:

var formElementName = $(this).attr('name'); var formElementId = $(this).attr('id'); var hiddenElementID = formElementId + '_autocomplete_hidden';

instead of: var formElementName = $(this).attr('name'); var hiddenElementID = formElementName + '_autocomplete_hidden';

On 11/23/2012 at 4:11:26 AM UTC phifi wrote:
34
i forgot: Thanks for this great Post! It helped me a lot...

Post a Comment




  



Spell Checker by Foundeo

Recent Entries



foundeo


did you hack my cf?