Playing with jQuery UI's Autocomplete Control

This post is more than 2 years old.

jQuery UI 1.8 has been out for a while now (see details on their blog) but I've yet to really find the time to play around with it. This weekend I finally took a look at it, specifically the new autocomplete widget, and I thought I'd whip up a few quick examples showing the control being used with ColdFusion.

To begin, I recommend taking a look at, and reading some of the docs, for the autocomplete widget. I'm only going to demonstrate a few aspects of it and the docs will give you the whole story. As with most things jQueryUIish (not a word, I know), you use the widget by simply pointing the library at a DOM item and "enabling" it. So for example, once I've got my libraries loaded, I can turn an input control into an autosuggest with one line of code. Obviously I can, and probably will, use more code to get fine grained control over the widget, but it really is pretty simple to use.

Let's start with a super simple example. This one is taken directly from the docs. The only thing I'll point out is - and this bugs me about all the jQuery UI demos, I'm going to show you the full source behind the code. It really bugs me that their View Source content never shows the included JavaScript and CSS commands. Yes, it is implied, but I know I had a hard time with this when I first began to use jQuery UI. When it comes to docs, I think it's always safe to assume less. Ok, mini rant aside. Here is a simple example of a static autocomplete. jQuery UI's autocomplete widget allows for both static, inline auto suggests as well as Ajax loaded content. We'll be looking at an example of that later on.

<script src="jqueryui/js/jquery-1.4.2.min.js"></script> <script src="jqueryui/js/jquery-ui-1.8.custom.min.js"></script> <link rel="stylesheet" href="jqueryui/css/vader/jquery-ui-1.8.custom.css" type="text/css" />

<script type="text/javascript"> $(function() { var availableTags = ["c++", "java", "php", "coldfusion", "javascript", "asp", "ruby", "python", "c", "scala", "groovy", "haskell", "perl"]; $("#tags").autocomplete({ source: availableTags }); }); </script>

<input id="tags" />

As you can see, we begin with our includes. We grab the core jQuery library, the jQuery UI library, and the style sheet. For my demos, I've chosen the Vader theme for obvious reasons.

My JavaScript consists of only two real parts. I've got a hard coded list of values in an array. Next, I "enable" the autocomplete on a input control (identified by the ID tags) and tell it to source by my array. And that's it. I really love how easy jQuery UI makes things sometimes. You can test this onlinehere.

Now let's make this a tiny bit dynamic. In my first ColdFusion version, I'll switch my categories to a ColdFusion variable. (And yes, this is still a static variable, but you can easily imagine it being sourced by the database.)

<cfset cats = "Adobe,Adoption,AIR,Books,ColdFusion,Flash,Flex,Groovy,Hardware,JavaScript,jQuery,Lost,MAX,Movies,Music,ORM,Politics,Television">

<script src="jqueryui/js/jquery-1.4.2.min.js"></script> <script src="jqueryui/js/jquery-ui-1.8.custom.min.js"></script> <link rel="stylesheet" href="jqueryui/css/vader/jquery-ui-1.8.custom.css" type="text/css" />

<script type="text/javascript"> $(function() { <cfoutput> var #toScript(listToArray(cats),"availableCats")#; </cfoutput> $("#category").autocomplete({ source: availableCats }); }); </script>

category: <input id="category" />

The first difference here is the cats variable. Again, this would normally come from the database but for now it's just a hard coded set of strings. Going down a bit, take a look at how I translate it to JavaScript. I make use of toScript, a ColdFusion function that translates variables into their relevant JavaScript versions. I first turn the list into an array however. After that, everything else is pretty much the same. You can take a look at this here. (And while there, do a View Source to see how the toScript generated my JavaScript.)

Ok, so while hard coded (or static) variables work, and are ok for small lists, most of the time you will want to load in the data via an Ajax call. The autosuggest widget makes that darn easy. If the value of the source attribute is a string, then jQuery treats it like a URL. In this example, I've pointed my source to a CFC:

<script src="jqueryui/js/jquery-1.4.2.min.js"></script> <script src="jqueryui/js/jquery-ui-1.8.custom.min.js"></script> <link rel="stylesheet" href="jqueryui/css/vader/jquery-ui-1.8.custom.css" type="text/css" />

<script type="text/javascript"> $(function() { $("#category").autocomplete({ source: "service.cfc?method=searchcategories&returnformat=json" }); }); </script>

category: <input id="category" />

Notice that I pass in my method and returnformat. You need to remember that CFCs, by default, return WDDX. Luckily it is easy to get around that (in ColdFusion 8 and higher). The docs did not make it clear, but the name of the argument sent to your server is term. Here is the simple CFC I used.

component {

remote function searchCategories(string term) {
	var q = new com.adobe.coldfusion.query();
	q.setDatasource("cfartgallery");
	q.setSQL("select mediatype from media where mediatype like :search");
	q.addParam(name="search",value="%#arguments.term#%",cfsqltype="cf_sql_varchar");
	var result = q.execute().getResult();
	return listToArray(valueList(result.mediatype));
}

}

As you can see, this is nothing more than a simple query. Notice my search string is dynamic on both sides of the term value. This allows me to handle partial matches, so a search for Cold would match both ColdFusion and Ice Cold Baby. If you want to match only results that begin with a term, you simply change how your server side logic works. You can demo this here. The search is against the media table of the cfartgallery demo, so try terms like "Pa" to see a few results.

Ok, so the final demo is pretty cool I think. One of the issues most autocomplete widgets suffer from is that while humans like to work with strings (like "Beer"), the database prefers unique identifiers (like 13). So given that you may return a string, again, "Beer", when you post your form to the server, how do you handle knowing that the value "Beer" referred to row 13 in your database? Typically you need to do another database query. Not a big huge deal, but wouldn't it be nice if your autocomplete could work with both strings and numbers? jQuery UI's autocomplete does this and does it well! Let's begin by modifying our CFC.

component {

remote function searchCategories(string term) {
	var q = new com.adobe.coldfusion.query();
	q.setDatasource("cfartgallery");
	q.setSQL("select mediaid as id, mediatype as value from media where mediatype like :search");
	q.addParam(name="search",value="%#arguments.term#%",cfsqltype="cf_sql_varchar");
	var query = q.execute().getResult();
	var result = [];
	for(var i=1; i&lt;=query.recordCount; i++) {
		result[arrayLen(result)+1] = {};
		result[arrayLen(result)]["id"] = query.id[i];
		result[arrayLen(result)]["value"] = query.value[i];			
	}
	return result;
}

}

In this example I've changed from returning an array of strings to returning an array of structs. Notice that I've got an ID and VALUE key being returned. (*) These values will be recognized by the widget, specifically the value attribute. By itself this won't solve our problem, but we can use the "select" option to handle the user selection event:

select:function(event,ui) { $("#catid").val(ui.item.id) }

This code says - when the user selects an item, grab the ID value and set it to the catid DOM item's value. Let's look at the complete page so it makes more sense.

<script src="jqueryui/js/jquery-1.4.2.min.js"></script> <script src="jqueryui/js/jquery-ui-1.8.custom.min.js"></script> <link rel="stylesheet" href="jqueryui/css/vader/jquery-ui-1.8.custom.css" type="text/css" />

<script type="text/javascript"> $(function() { $("#category").autocomplete({ source: "service2.cfc?method=searchcategories&returnformat=json", select:function(event,ui) { $("#catid").val(ui.item.id) } }); }); </script>

<form action="test3.cfm" method="post"> category: <input name="category" id="category" /> <input name="catid" id="catid" type="hidden"> <input type="submit" value="Submit"> </form>

<cfif not structIsEmpty(form)> <cfdump var="#form#" label="Form"> </cfif>

As you can see, I've added the select handler to my widget constructor. I've also added the hidden form field catid. Finally I added a real submit button and a cfdump so I can see the result. Now when I select a media type, the user will see the nice string, and the hidden form field gets the proper primary key. You can see this for yourself here. All in all I think it works really nicely.

Again - please note there is more to this control then what I've shown here. Check the docs and have fun with it! (And if you are using it in production, please feel free to share the URL here.)

* Did you notice I used struct notation ["id"] instead of dot notation? Dot notation creates JSON with upper case keys. jQuery UI won't pick up on that automatically. By using bracket notation I ensure my JSON maintains the same case.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Matt Gifford AKA coldfumonkeh posted on 4/12/2010 at 5:51 PM

Great post Ray.

I've just finished writing a magazine tutorial on the revised 1.8 UI, and had great fun playing around with the new features in the library, especially the autocomplete widget.

I love the use of the source param pulling in the data from the web service, and jQuery makes it incredibly easy to pull out the information as you've shown here using the ui.item method.

CF and jQuery go together incredibly well - both rapid development, both extremely extensible, both with a great community.

Comment 2 by Lola LB posted on 4/12/2010 at 5:55 PM

Am I missing something obvious with the demo . . . when I go to the demo it comes looking plain-vanilla form with no skinned elements. And, how would one hook it up using the Solr search engine? I'm thinking, like keep track of tables with entered information about stuff like book titles and descriptions of plots, and user searches for a particular book and it would "look" ahead for matching strings to search on.

Comment 3 by Raymond Camden posted on 4/12/2010 at 6:01 PM

@Lola: Exactly Lola - it is an autosuggest widget. You won't see _anything_ at first. Begin typing in the control field though, like the letter e, and you should see something.

As to your second point - you would simply change the db query to a cfsearch call instead.

Comment 4 by Robert Zehnder posted on 4/12/2010 at 6:22 PM

I would be interested to see how it handles extremely long matching result lists. I have a place I was thinking about writing the auto complete in. Until it gets drilled down a bit things might be a little hairy (hundreds of results).

Thanks for the nice little demo Ray.

Comment 5 by Raymond Camden posted on 4/12/2010 at 6:34 PM

@Robert: Two things. One- you can control _when_ the auto suggest begins to look. There is a minlength attribute.

Secondly - _you_ have ultimate control over the data. I could have easily added a maxrows/top/limit to my query to keep things under control.

Comment 6 by Mike posted on 4/12/2010 at 7:11 PM

One thing that confused me for a few seconds in the demo...the auto-suggest list is case-sensitive. It threw me off when "p" didn't return "Painting". This is just a DB thing, and not a jQuery issue.

Comment 7 by James Moberg posted on 4/12/2010 at 7:22 PM

When using the demo "p" returns "Photography" but not "Painting". I thought this sample only returned 3 results, so I typed "pain". No results.

I can search for "hotogr" and "Photo", but not "pho".

Is this a jQuery issue? Is there a trick to not having it be case-sensitive? (I use a different jquery autosuggest plugin and was eager to see a demo of this one.)

Comment 8 by Jen posted on 4/12/2010 at 7:30 PM

I did something similar but with US states. It uses a call to a cfm page and serializeJSON to return the results.
http://www.jensbits.com/201...

Comment 9 by Raymond Camden posted on 4/12/2010 at 7:38 PM

@James: Yes, the db is case sensitive. I should have made that clear. That's a db issue - not a jQuery issue.

Comment 10 by Russ S. posted on 4/12/2010 at 11:40 PM

That's a sweet tip about how to return lower-case JSON variables from a remote CFC. I have always hated how CF serializes variable names to upper-case. Any idea why CF doesn't maintain the original case?

Comment 11 by Raymond Camden posted on 4/12/2010 at 11:44 PM

There isn't an original case really. When you do x.y=1, you aren't specifically a string, but a variable name. Well, that's my opinion anyway. There is probably some much more technical low-level reason why. ;)

Comment 12 by Robert Zehnder posted on 4/13/2010 at 12:13 AM

I generally use bracket notation on a set and I suppose it has kept me out of trouble because I generally camel-case my vars. I also use *a lot* of AJAX/JSON and haven't really run in to a case problem. The one notable exception being returning queries through JSON.. :/

Comment 13 by Mike posted on 4/13/2010 at 1:11 AM

Thanks for the post Ray - I implemented a jQuery autocomplete a few months ago using calls to a cfm file. I'll remember this example if I want to tie it to a cfc instead. Do you think there is a performance gain doing the call with a component instead?

Comment 14 by Raymond Camden posted on 4/13/2010 at 1:14 AM

Performance - not really. I used an example of hitting a CFC because, typically, the type of data I'd need would come from a CFC.

Comment 15 by Tom posted on 4/13/2010 at 3:02 PM

jQuery is indeed quite easy to use.jQuery coupled up with CF is efficient for the development process.But I agree with Lola on it's dubiousness about usage with Solr search engine and also will the case sensitive factor remain with JSON when used by solr as output. I also reviewed Solr's complete reference guide (http://www.lucidimagination... ) for concept insights and found it useful.

Comment 16 by Raymond Camden posted on 4/13/2010 at 3:11 PM

I'm sorry - maybe I'm not quite getting you. It isn't case sensitive. My DB is. And I could have gotten around that I'm sure.

Comment 17 by Michel posted on 4/16/2010 at 11:36 AM

Hi,
Not really about autocomplete, but as you said that you had work a lot with JQuery the last time (and jqgrid ?), Could you maybe have an example on how to join a jqgrid cell to a popup window to show data from another table related to the clicked cell (foreign key)
I tried this with the fancybox(http://fancybox.net/home) plugin as follow:
custom formatter to show an icon and to put an id attribute to the 'a' tag as the plugin requires an id attribute. then I should have to link this id attribute to the .fancybox method... but... someone has maybe an idee to accomplish this ?
Greetings,
Michel

Comment 18 by Raymond Camden posted on 4/17/2010 at 5:50 AM

It sounds like you are saying - when a user clicks a row, show a dialog window - right?

Comment 19 by Michel posted on 4/17/2010 at 8:55 AM

Right, or more, when a user clicks a particular cell where you see an icon, but the data is the key to details data. This should have to open a popup window with those details. I got it working, but it opens the window I call to make the query. What I should like is to get this data not in a reloaded window, but in a little popup... and ideally in the fancybox jquery plugin... or what should also be nice in a tootip -)
Thanks for your reply,
Michel

Comment 20 by Raymond Camden posted on 4/19/2010 at 5:48 PM

Well it certainly should be possible. :) I know jqGrid is very powerful and obviously allows you to respond to click events. It sounds like you got that, but you need to get the data from the client side where it already exists. If you look at the jqGrid API (I'm there now) you can see methods to get the data from the grid.

Comment 21 by Michel posted on 4/20/2010 at 3:37 PM

I confirm, it is possible -)
I made a custom formatter to add an id attribut to the cell data (and btw an icon), and from there
I call a cfm giving the key as parameter to retrieve the data.
And instead of loading this in another page, I try to show this in a fancybox jquery plugin with this:

gridComplete: function(){
$("a[id='userDetails']").fancybox({'type':'ajax'});
}
});
My problem was only to get the userDetails id of the a tag to link it to the fancybox method.
This did nothing: $('#userDetails), but this is ok: $("a[id='userDetails']")

Thank you for your reaction,
Michel

Comment 22 by Srinivas posted on 4/21/2010 at 1:50 PM

Hi Ray,

I am newbie to jQuery.Kindly help for the below requirement.

I am having 3 controls say Department, Locations & Name.

In search form,If the user chooses a department with auto suggest & then he comes to location, we need to show all locations of that department in auto suggest and when he comes to Name control,we need to show only names of the persons working in selected values of department & location controls.

Like the way we need to filter, for the user chooses any of the control.

Let me know if you have any questions.

Thanks in advance

Comment 23 by Raymond Camden posted on 4/21/2010 at 10:33 PM

I'll be happy to help, but I think you have everything you need already. Remember the last part of my demo specifically mentions how you can store a primary key for the string in a hidden form field. You would use that value then for your second and third autocomplete lookups. You could just append the value to the URLs used.

Comment 24 by Srinivas posted on 4/24/2010 at 8:12 AM

Hi,

I am getting an empty string, when I try to read out a value of a first text box which I am using as a URL param for second text box.
Any clues,code as follows.

$(function() {
$("#department").autocomplete({
source: "test2.cfm"
});
$("#location").autocomplete({
source: "test2.cfm?department="+$("#department").val() //Value in the department text box need to get here & results need to be filtered based on Department
});
});

<form name="frm" action="test.cfm" method="post">
Department: <input id="department" />
Location: <input id="location" />
</form>

Comment 25 by Raymond Camden posted on 4/24/2010 at 11:24 PM

Is the full code online where I can run it? This is really a simple thing- it should work. :)

Comment 26 by Srinivas posted on 4/27/2010 at 9:58 AM

From Ray:
*********
$("#department").autocomplete({
source: "test2.cfm?vType=department",
select:function(event,ui) {
var sel = ui.item.value
$("#location").autocomplete("option","source","test2.cfm?vType=location&department="+escape(sel))
}
});

Thanks Ray, its working pretty good now.

Comment 27 by Raymond Camden posted on 4/27/2010 at 3:07 PM

I'll be doing a blog entry today that demonstrates this more fully.

Comment 28 by Raymond Camden posted on 4/27/2010 at 5:09 PM

Follow up blog post: http://www.coldfusionjedi.c...

Comment 29 by MikeQ posted on 7/28/2010 at 9:07 PM

I keep getting this error:
a is null
"string"){c=this.options.source;this.s...=this._normalize(a);this._suggest(a);

Any ideas?

Thanks
Mike

Comment 30 by Raymond Camden posted on 7/29/2010 at 11:32 PM

Nope - is it online where I can see it?

Comment 31 by Mike posted on 8/3/2010 at 5:00 PM

I'm all good now. I got a hint from another post where requestCFC was causing problems and apparently that was my issue too.

Thanks
Keep up the good work :)

Mike

Comment 32 by mauricio posted on 8/20/2010 at 1:47 AM

hey raymond sorry bother you but its that the real CFC code? im newbee im and copying and pasted but

dosnt work

Comment 33 by Raymond Camden posted on 8/20/2010 at 4:10 PM

It was short enough to fit into a comment:

component {

remote function searchCategories(string term) {
var q = new com.adobe.coldfusion.query();
q.setDatasource("cfartgallery");
q.setSQL("select mediatype from media where mediatype like :search");
q.addParam(name="search",value="%#arguments.term#%",cfsqltype="cf_sql_varchar");
var result = q.execute().getResult();
return listToArray(valueList(result.mediatype));
}

}

Comment 34 by jim&aposs posted on 10/11/2010 at 7:08 AM

i have the same question about this cfc code its that the real CFC code? and its doesnt work, can i get the full source code of the demo page, please ray

Comment 35 by Raymond Camden posted on 10/12/2010 at 1:03 AM

Not quite sure I get you. How does the CFC code not work? Can you be more specific? As for the code for the front end - you just need to view source.

Comment 36 by jim&aposs posted on 10/15/2010 at 6:42 AM

Sorry Ray im newbee, i paste this code to a new cfc file
component {

remote function searchCategories(string term) {
var q = new com.adobe.coldfusion.query();
q.setDatasource("cfartgallery");
q.setSQL("select mediatype from media where mediatype like :search");
q.addParam(name="search",value="%#arguments.term#%",cfsqltype="cf_sql_varchar");
var result = q.execute().getResult();
return listToArray(valueList(result.mediatype));
}

}

should it use
<cfcomponent>
<cffunction>
"the code"
<cffunction>
<cfcomponent>

or could you just share the whole source, please.

Thank u Ray

Comment 37 by Raymond Camden posted on 10/15/2010 at 4:51 PM

No, the code is the whole source. It is a script based CFC. Are you on CF9? If not - the code will not work for you. You would need to convert it to a tag based one - including changing the script based query too. Shouldn't take more than 3 minutes though.

Comment 38 by jim&aposs posted on 10/18/2010 at 1:32 PM

Oh i see, im running it on CF 8 ,okey i get it

Thank You Ray

Comment 39 by Jay posted on 10/29/2010 at 11:51 PM

Hey I know this post is a bit old but I was wondering if you know how I would go about using this being able to type multiple categories in. If you have any ideas on it please let me know.

Thanks
-Jay

Comment 40 by Raymond Camden posted on 10/29/2010 at 11:51 PM

How would it work? Like after you pick one would it add a comma and let you type more?

Comment 41 by Jay posted on 10/30/2010 at 12:04 AM

That is exactly how I would want it to work.

Comment 42 by Jay posted on 10/30/2010 at 6:25 AM

What do you think? Worth pursuing with jqueryui or should I see if there is another implementation out there that can do something like that?

Comment 43 by Raymond Camden posted on 11/2/2010 at 3:24 PM

Looks like jQuery UI already supports it:

http://jqueryui.com/demos/a...

Comment 44 by Jay Reichenbach posted on 11/2/2010 at 4:53 PM

Thanks Ray that's a good start. I'll have to configure it to have a hidden field with to put the ID's in for each selection. Thanks!

Comment 45 by Jeana posted on 11/22/2010 at 11:41 PM

Thank you so much for this tutorial. It is the only reason that I got Autocomplete working on my current development project.

Comment 46 by Raymond Camden posted on 11/23/2010 at 12:00 AM

Glad to be of service!

Comment 47 by Ryan posted on 12/19/2010 at 11:21 AM

love the lowercase json return. Any issue with using the following structure instead:

for(var i=1; i<=query.recordCount; i++) {
result[arrayLen(result)+1] = {
"id" = query.id[i],
"value" = query.value[i]
};
}

Comment 48 by Raymond Camden posted on 12/19/2010 at 9:05 PM

If that's JS, then you need to use arr.length, not arrayLen(arr). arrayLen is a CF function.

Comment 49 by Bobbytuck posted on 1/10/2011 at 9:58 PM

Is it possible to supply a zip with the full source code here? I mean, a complete zip file. I'm confused about implementing the CFC (new to CF -- but I'd love to see a specific example).

Does anything else need to be added to the CFC above?

Confused. (I just name it with the .cfc extension?)

Comment 50 by Raymond Camden posted on 1/10/2011 at 10:00 PM

Unfortunately I don't think I have the full folder anymore. I can say that the first script is a regular CFM. You can call it whatevr. Ditto for the very last code sample.

The CFC should be named service2.cfc. You can tell this by the URL used in the last code sample.

Does that make sense?

Comment 51 by Simon Hine posted on 2/13/2011 at 12:22 PM

Thanks (again and as usual) for a really helpful post -

I'm missing something though - I'm getting a JSON return as I'd expect (according to firebug) - but no suggestion is appearing in the field. Any advice appreciated thanks Ray.

jquery:
$("#category").autocomplete({
source: "getNames.cfc?method=getContacts&returnformat=json"
});

and on the page:
<input type="text" id="category" />

Comment 52 by Raymond Camden posted on 2/14/2011 at 5:00 AM

Looks fine to me. Is this online where I can see?

Comment 53 by Simon Hine posted on 2/14/2011 at 5:19 AM

Sorry Ray - it's not. I can publish it tonight (Australian time about 8 hours from now) or I can send you files in a zip.

Thanks for the prompt reply.

Comment 54 by Raymond Camden posted on 2/14/2011 at 5:22 AM

It's easier if you just let me know when it's live. No rush.

Comment 55 by Simon posted on 2/14/2011 at 6:57 AM

Fair enough - had a window of connectivity and was able to bump up the site. The query in the cfc uses a cookie based ID so you will need to log in (username=simon@hinesight.com.au pwd=simon) to see the functionality.

On the newAppointment page is the text field in question - entering s returns json data Simon and Sam but nothing appears in the field.

Really appreciate the help. Thanks

Comment 56 by Raymond Camden posted on 2/14/2011 at 7:14 AM

Did you mean to tell me the site so I can login? :)

Comment 57 by Simon Hine posted on 2/14/2011 at 7:54 AM

echoes of "help me to help you" in my ears...
sorry - I added the site to the website field in the comments box- http://www.yournextvisit.co...

Thanks again Ray, apologies for being a bit of a dolt!
Simon

Comment 58 by Raymond Camden posted on 2/15/2011 at 12:28 AM

You aren't returning the values in the way. View my demo with Firebug (or Chrome tools), and you can see how the data is different. I made use of listToArray in CF. You are returning a query object I think.

Comment 59 by Simon posted on 2/15/2011 at 9:15 AM

Thanks Ray - I think my problem is to do with my attempt to translate your script cfc to a tag based one (still on CF 8).

This is what I tried:
<cfargument name="term" required="false" default=""/>

<cfset var myQuery = "">
<cfset var searchFor = arguments.term>
<cfset result = arrayNew(1)>

<cfquery name="myQuery"
query statements here
</cfquery>

<cfloop query="myQuery">
<cfset result[myQuery.currentRow] = structNew()>
<cfset result[myQuery.currentRow].firstName = myQuery.contactFirstName>
</cfloop>

<cfreturn result>

I'm not sure that the cfloop at the end is doing what I need.

Your data returns like:[{"value":"Painting","id":"1"}]
mine is currently like: [{"FIRSTNAME":"Simon"},{"FIRSTNAME":"Sam"}]

Thanks again for your help, it's really appreciated.
Simon

Comment 60 by Raymond Camden posted on 2/15/2011 at 9:18 AM

Well, first off, you want to try for lower case just to make your JS code a bit more readable. That's easy to do. Change .firstName to ["firstname"] or even ["firstName"]. Then you have the issue of letting the auto complete know what to use for display and ID. I don't remember the options offhand, but try using value instead of firstname for now.

Comment 61 by Simon posted on 2/15/2011 at 9:56 AM

Ok - I've amended the end of the cfc like so:
<cfset result[myQuery.currentRow] = structNew()>
<cfset result[myQuery.currentRow].id = myQuery.ID>
<cfset result[myQuery.currentRow].value = myQuery.value>

and I'm now seeing data that looks more like the data in the example - and I'm getting no errors in firebug. When I enter a value in the filed a container for the autosuggest appears, but still has no content.

I've uploaded the amended files if you want to observe the behavior I'm talking about, and I'm heading over to the jquery doco to revisit again. Thanks for the help (again).
Simon

Comment 62 by Raymond Camden posted on 2/15/2011 at 9:59 AM

You are still using "dot" notation, .id, .value. Change to bracket notation:

["id"]
["value"]

Comment 63 by Simon posted on 2/15/2011 at 10:03 AM

Awesome!

That got it Ray - thanks so much (for the patience as well as the help).
Simon

Comment 64 by Michael posted on 2/18/2011 at 3:12 AM

Hey Ray,
Have you ever seen the page throw an SQL command not properly ended error on the cfc? Here's some of the key debug info:
[Macromedia][Oracle JDBC Driver][Oracle]ORA-00933: SQL command not properly ended

The error occurred in C:\ColdFusion9\CustomTags\com\adobe\coldfusion\base.cfc: line 449

449 : <cfloop index="i" from="2" to="#ArrayLen(sqlArray)#">

And the query looks something like this:
select distinct table_column, table_column_id from db.table where table_column like (param 1) limit 0,15

It's odd that it is doing this. I mean, I barely touched any of the example code. I'm just researching if something like this would work for a page I'm working on.

I know there was a bug with CF9 that could cause this to occur

Comment 65 by Michael posted on 2/18/2011 at 3:33 AM

Nevermind, I had to check my sytax a little better. Looks like I had a small typo. Thanks anyways.

Comment 66 by Travis posted on 4/21/2011 at 1:05 AM

I am using Coldfusion MX 7 and had to utilize a different JSON solution because I don't have the luxury of CF8 (bummer). I'm also using Model-Glue. So, how do i get the search term in my controller since i can't just add an argument called term to my function?

Comment 67 by Raymond Camden posted on 4/21/2011 at 1:08 AM

Your Ajax calls pass data either via a GET call or POST. But that doesn't matter as Model-Glue will combine them all into the Event scope. So in MG, you just grab what was passed in and pass it to your model.

Comment 68 by Pritesh posted on 4/21/2011 at 1:09 PM

here is coldfusion wrapper for autocomplete in case anyone interested
http://www.thecfguy.com/pos...

Comment 69 by Josh posted on 6/9/2011 at 9:48 PM

I'm running into a problem where the values in the database contain commas; when I output the query results using the following, post titles with a comma in them return as two results instead of one.

<cfreturn listToArray(valueList(qSiteAutoCompleteSearch.postTitle)) />

Any idea on how to fix this?

Comment 70 by Raymond Camden posted on 6/9/2011 at 9:51 PM

Writing this by hand - ignore errors.
<cfset arr = arrayNew(1)>
<cfloop query="qSiteAutoCompleteSearch">
<cfset arrayAppend(arr, postTItle)>
</cfloop>

Comment 71 by Josh posted on 6/9/2011 at 10:13 PM

You are a beast! (That's a good thing.) Thanks, Ray. Not sure why I didn't think of that. Some days I wonder if I should take up funambulism.

Comment 72 by Raymond Camden posted on 6/9/2011 at 10:22 PM

Thanks for sending me to the dictionary. ;)

Comment 73 by Henry posted on 8/5/2011 at 4:22 AM

Hi. Thanks for the excellent tutorial. I was lost for a while with why the suggestions weren't displaying in my development environment. Firebug displayed the json from my cfc ok and everything else was fine. Then I had a mini brainwave and turned cfdebugging off and the suggestions magically appeared. Has anyone else had this issue and found a workaround that doesn't require turning debugging off? Cheers!

Comment 74 by Raymond Camden posted on 8/5/2011 at 4:57 AM

Just turn debugging off the _that_ request. In your CFC method:

<cfsetting showdebugoutput="false">

Comment 75 by Henry posted on 8/8/2011 at 5:04 AM

Thanks Ray!

Comment 76 by mnoppe posted on 9/6/2011 at 6:27 PM

Thanks Ray for your twitter answer, as usual you rocks :)
So I first tried to follow your second example, and made the wsdl result call in a variable, and everything is so OK, but when I try to call www.mydomain.com/cfc/MyWebs... directly in the source of the autocomplete, I see in the firefox console that the term variable is appended but the call doesn't show any result. Did I made a wrong call to the wsdl ?
Michel

Comment 77 by Raymond Camden posted on 9/6/2011 at 6:41 PM

First off - I hate people who get pedantic about language, but you aren't using WSDL here. WSDL is a term that refers to a form of XML used when talking to web services. CFCs can output WSDL but you aren't using that feature here. (And since I said pedantic above it pretty much guarantees someone is going to call me out on it. ;)

Ok - that being said, did you look in the FIrebug _console_ or the Network tab? It's a subtle difference and you probably meant console as a way to refer to all of Firebug, but they are separate tools within FIrebug itself. If you are indeed in the Network tab and not seeing anything, maybe scroll down. Don't forget CF can sometimes output a bunch of white space.

It would be best if you could share a public URL so we can see. Or if you want to email me directly, that's fine. (Although I ask that when we find the issue you share the result back here.)

Comment 78 by Jason Asch posted on 10/12/2011 at 3:54 AM

Ray: any way to do your code above that does not reference the custom CF tags in CF9. Your code works on my local machine but when I upload it to the server I get an error calling the var q = new com.adobe.coldfusion.query(); So I'm assuming my shared hosting environment that the mapping is not there for such functionality. see here: http://www.northernkyhomese...

Comment 79 by Raymond Camden posted on 10/12/2011 at 4:00 AM

Just rewrite my script-based CFC as an old school tag based one. Or, you can find out where CF is installed by cfdumping the server scope. Note the root directory. In your Application.cfc, add a new custom tag path that points to (rootdir)\customtags.

Comment 80 by Jason Asch posted on 10/12/2011 at 6:37 AM

Sorry Ray not following you as I'm a newb to this kinda coldfusion (cfc's, custom tags, CF9). I ran some code regarding the server scope and I think I found the root directory (on a shared environment) but as far as the custom tag in the cfc you wrote not sure what's up there.

Comment 81 by Raymond Camden posted on 10/12/2011 at 6:40 AM

Do you know how to use the Application.cfc feature? There's docs on that, and blog posts here, in Google, etc. It's a 'controller' for your CF apps and can be used to set things like custom tag paths. Read up on that, and then make use of the feature. It should be as simple as adding

<cfset this.customtagpaths = "(yourroot)\customtags">

to the file. If that doesn't work, well, I'd look at the docs for CFCs in general. It's a big topic, but one you need to pick up on sooner or later anyway. To be honest, the code above could be rewritten in about 5 minutes once you get a hang of the syntax.

Comment 82 by Jason Asch posted on 10/12/2011 at 6:43 AM

Oh I know what an application.cfc is as I'm currently using one with limited knowledge talking to you of course. I guess I'm not sure how deep to go into the drive as I'm in a shared environment.. the path seems pretty deep all the way down to the c: drive.

Comment 83 by Raymond Camden posted on 10/12/2011 at 6:48 AM

I wrote this version -very- quickly - so it may not work 100%:

http://pastebin.com/Yq68rdR9

Comment 84 by Jason Asch posted on 10/12/2011 at 7:32 AM

You are the man... I can't wait to play for that, thank you for taking the time. So I have added the following to my Application.cfc after tracking down the root of the server:
<cfset this.customtagpaths = "C:\glassfish3\glassfish\nodes\node1\cf01\applications\cfusion\WEB-INF\cfusion\CustomTags\">
Still not having any luck getting the functionality to work online... locally yes but not on the stupid shared environment.

Comment 85 by Raymond Camden posted on 10/12/2011 at 5:20 PM

Maybe do a quick check using directoryExists? It's possible the custom tags aren't there.

Comment 86 by Jason Asch posted on 10/12/2011 at 7:38 PM

I'm checking with my hosting provider who is apparently have never been asked this before... as they don't know what I'm talking about :) Also, in your new code (component) posted above I noticed you did not reference the customtag or query (cfset var q = "") is there a reason or do you need to have this to make the code work. I used your new function locally and still can't get the new code to work. As always, thank you for your time and hard work.

Comment 87 by Jason Asch posted on 10/12/2011 at 7:51 PM

As of right now this is what I have so far:
http://pastebin.com/tGxrJF9z

Comment 88 by Raymond Camden posted on 10/12/2011 at 8:08 PM

To your first comment - the new pastebin is a tag based version of the code. I know you are new to CF, but you have done queries before, right? When you tried it locally, what error di you get?

Comment 89 by Raymond Camden posted on 10/12/2011 at 8:09 PM

Remove this line:

<cfset var q = new query()>

Make it

<cfset var q = "">

Comment 90 by Jason Asch posted on 10/12/2011 at 8:20 PM

Sorry Ray... I just updated that code locally and still can't get it to work... link above has been changed as well as a reference. Just to recap your original code (cfc) works locally not on the server, the new reformated cfc does not work on either for me. Any other thoughts?

Comment 91 by Raymond Camden posted on 10/12/2011 at 8:22 PM

At this point it makes sense to switch off blog. Basically, I'd focus on the tag based version. You say it doesn't work, but how? Did you check the CF logs for an error? Did you try using Firebug or Chrome network tools ? THey would show the response from the CFC and help isolate the issue. Follow up with me off blog though please.

Comment 92 by Jason Asch posted on 10/12/2011 at 8:25 PM

Ok sorry about that. How to contact you via contact form?

Comment 93 by Raymond Camden posted on 10/12/2011 at 8:52 PM

See "Contact Me" waaaay up there on top? :)

Comment 94 by vishal posted on 1/4/2012 at 6:12 PM

If i dont want to change text box value unless final selection of suggestion then what can ido..in where exactly i want to made change...

Comment 95 by Raymond Camden posted on 1/4/2012 at 7:36 PM

I have no idea what you mean. Are you saying you don't want to allow free form text, just values from the suggest?

Comment 96 by James Moberg posted on 1/4/2012 at 8:28 PM

I've been using Drew Wilson's AutoSuggest jQuery Plugin. It feels a lot like Facebook's AutoSuggest and allows you to allow free text additions, restrict to only certain values and also allow multiple values.
http://code.drewwilson.com/...

Comment 97 by joeskeebo posted on 1/26/2012 at 12:35 AM

Damn Ray you look like a homeless mutha with that beard, hat and whatnot.

Comment 98 by Raymond Camden posted on 1/26/2012 at 12:37 AM

Heh, what can I say - I'm a bum. ;)

Comment 99 by sally posted on 2/19/2012 at 9:28 PM

Please can you tell me how to use in coldfusion 8 can't get to work that's my cfc
:
<cffunction name="getNames" access="remote" returntype="String" >
<cfargument name="search" type="any" required="false" default="">

<cfset var data="">
<cfset var result=ArrayNew(1)>

<cfquery name="data" datasource="dbNAme">
SELECT NAME
FROM myTable
WHERE NAME LIKE '%#trim(ARGUMENTS.search)#%'
ORDER BY NAME
</cfquery>

<cfloop query="data">
<cfset returnStruct = StructNew() />
<cfset returnStruct["label"] = NAME />

<cfset ArrayAppend(result,returnStruct) />
</cfloop>

<cfreturn serializeJSON(result) />
</cffunction>

and im this my cfm:

<script src="jquery-1.4.2.min.js"></script>
<script src="jquery-ui-1.8.custom.min.js"></script>
<link rel="stylesheet" href="jquery-ui-1.8.custom.css" type="text/css" />

<script type="text/javascript">
$(document).ready(function(){
$('#Names').autocomplete(
{source: function(request, response) {
$.ajax({
url: "cfc/getValues.cfc?method=getNames>&returnformat=json",
dataType: "json",
data: {
search: request.term,
maxRows: 10
},
success: function(data) {
response(data);
}
})
},
parse: function(data){
return $.map(data, function(item) {
return { data: item, value: item, result: item };
});
}
});
});
</script>

category: <input id="Names" />

but i can't get to work

Comment 100 by Raymond Camden posted on 2/20/2012 at 12:53 AM

The reason it isn't working is because you are converting the result to json here:

<cfreturn serializeJSON(result) />

but you told CF to convert it for you here too:

url: "cfc/getValues.cfc?method=getNames>&returnformat=json"

(I assume the > is a typo, if not, that's a problem)

Basically, you are turning JSON into JSON. Change your cfreturn to be just

<cfreturn result>

Btw, not to sound like a broken record, but if you use Google Chrome Dev Tools or Firebug, you would have seen the result and noticed it was double encoded JSON. I strongly urge folks to use tools like this so you can see what is being returned.

Comment 101 by Sally posted on 2/20/2012 at 11:29 AM

Thanks for the information but the cfc page isn't being called.No javascript error but when i write in the textbox nothing happens.sorry Im new to coldfusion :)

Comment 102 by Sally posted on 2/20/2012 at 6:02 PM

Need to know if there is any error in my query string that calls the cfc file cause the ajax call is not being performed .

Comment 103 by Raymond Camden posted on 2/20/2012 at 6:46 PM

Did you try removing the > from the url?

Comment 104 by Sally posted on 2/20/2012 at 7:06 PM

Yes this is typing mistake this > is not contained in my url .

Comment 105 by Sally posted on 2/20/2012 at 7:21 PM

Even if i change the cfc file name no error is fired what could it be the reason i need ? Im using CF 8

Comment 106 by Raymond Camden posted on 2/20/2012 at 7:28 PM

Do you see a network request at all in Firebug or Chrome Dev Tools?

Comment 107 by Sally posted on 2/20/2012 at 7:39 PM

No Network request are shown

Comment 108 by Raymond Camden posted on 2/20/2012 at 9:01 PM

Well, is it online where we can all see?

Comment 109 by ben posted on 2/21/2012 at 6:15 AM

hi ray. thanks a lot for the post on using autocomplete with CFC's. I'm noticing that demo2 and demo3 don't work in firefox. demo 1 works ok.
I think I can figure out how to use it based on your examples, but wanted to let you know the demos don't seem to working.

Comment 110 by Raymond Camden posted on 2/21/2012 at 10:46 AM

Ugh, it looks like the artgallery db isn't set up right for my server, which means lots of demos will be down. Will try to fix later this week.

Comment 111 by Raymond Camden posted on 2/21/2012 at 10:52 AM

Fixed.

Comment 112 by ben posted on 2/21/2012 at 11:44 PM

thanks ray. I saw that in firebug last night, but wanted to let you know. (not that you don't have enough to do, or people to help!)

thanks to your post, I'm levitating x wing fighters out of swamps with autocomplete!

cheers

Comment 113 by Sally posted on 2/22/2012 at 11:31 AM

I've tried to add error function to my script
like this :
error: function (xhr, textStatus, errorThrown){
// show error
alert(errorThrown);
}
when i try to write in the textbox i have an alert with undefined value inside. Sorry but it isn't published online .

Comment 114 by Raymond Camden posted on 2/22/2012 at 6:04 PM

What about textStatus?

Unfortunately - if I can't see this myself, I'm limited on how much more I can help.

Comment 115 by Ray posted on 3/16/2012 at 3:03 AM

Is there a way to apply this autocomplete feature to cfgridcolumn instead of just a text field? I have a client who wants the job description field to autocomplete using a query result of previous descriptions.

Comment 116 by Nath posted on 5/24/2012 at 10:22 AM

In fireFox I can see results in this Form :
"[{\"label\":\"AABDALLAH\"},{\"label\":\"AABDALLAH\"}.....
but nothing appearing in the Textbox how i can i fix this issue

Comment 117 by Raymond Camden posted on 5/24/2012 at 6:55 PM

+Ray: cfgrid makes use of Ext - an entirely different JavaScript UI framework. I'm sure something like that could be done. But not with the jQuery UI plugin. It's totally different.

+Nath: I don't know. :) What else do you see? Do you see an error? Is it online where I can run it?

Comment 118 by Gary posted on 6/15/2012 at 9:45 AM

Just wanted to say thank you very much, I have wasted hours trying to get the ability to send a hidden field as described above and finally I have it. Once again many thanks!

Comment 119 by Raymond Camden posted on 6/19/2012 at 5:56 AM

Glad it was helpful.

Comment 120 by Mark Gregory posted on 7/22/2012 at 11:01 PM

Coming in a bit late, but have a fun fact.
If you will be returning numeric values for the dropdown, you will want to use quotedValueList instead of valueList. Otherwise you get this:
[123,234,345]
Instead of:
["123","234","345"]

The result without the quotes is that the JQuery autocomplete dropdown is created, but with no values.

This is something easily figured out in a few minutes. Unless you are stubborn and sleep deprived. Not that I am, but just sayin'...

There is probably a better way, but this works too.

Comment 121 by Raymond Camden posted on 7/23/2012 at 6:21 AM

Thanks for sharing that!