AutoSuggest Example
I've added autusuggest to ColdFusionBloggers.org and thought I'd talk a bit about how I did it (and about the problems I ran into).
First off - using autosuggest is extremely simple. All you have to do is take a standard input tag and switch it to a cfinput tag instead. Then just add the autosuggest attribute and your done. Thats it. Well, ok, you have to hook up the autusuggest to either a static list of suggestions, or to a dynamic data source.
For ColdFusionBloggers.org I decided the autusuggest would be based on previous searches. I added a logSearch() method to my entries CFC. This logged the search term and the time. I then added a method to return results based on what you type in the search box:
<cffunction name="getSearchHelp" access="remote" returnType="array" output="false">
<cfargument name="term" type="string" required="true">
<cfquery name="q" datasource="#variables.dsn#">
select distinct searchterm
from search_log
where searchterm like <cfqueryparam cfsqltype="cf_sql_varchar" value="#left(arguments.term,255)#%">
limit 0,10
</cfquery>
<cfreturn listToArray(valueList(q.searchTerm))>
</cffunction>
Notice I used #term#% for my search, not %#term#%. Why? Remember that autusuggest is based on what you type. If you type "R", you should see suggestions that start with R.
Then I ran into my first problem. Notice the datasource is variables.dsn. My Application.cfc file had created and initialized an instance of entries.cfc. Guess what happened when I hooked up ColdFusion directly to the CFC? Because I was accessing the CFC directly, variables.dsn wasn't set properly. I fixed it by changing to application.dsn, which worked, but I wanted a nicer solution.
The cool thing about binds in ColdFusion 8 is that you can link to CFCs, JavaScript functions, and random URLs. So my cfinput which had been using a CFC:
<cfinput name="search_query" autosuggest="cfc:components.entries.getSearchHelp({cfautosuggestvalue})" maxResultsDisplay="10">
Was switched to this version:
<cfinput name="search_query" autosuggest="url:searchhelpproxy.cfm?term={cfautosuggestvalue}" maxResultsDisplay="10" showAutoSuggestLoadingIcon="false" size="10" />
I then added searchhelpproxy.cfm:
<cfif structKeyExists(url, "term") and len(trim(url.term))>
<cfinvoke component="#application.entries#" method="getSearchHelp" term="#url.term#" returnVariable="result">
<cfoutput>#serializeJSON(result)#</cfoutput><cfabort>
</cfif>
This file simply invokes the method I built but uses the Application scoped CFC instead. Notice that I have to format the result into JSON. Also note that Ben has blogged about some nice modifications made to autosuggest and cfselect bound controls.
If I have to do this again, I'll most likely create a more generic file that can handle different operations.
One last issue. I noticed that when I used the autusuggest control, it broke my layout a bit. I've pinged Adobe about this, but for now I've tried to make it work better by adding some style to my cfinput. In general I do not see a good reason why this should have any impact on layout, but maybe I did something wrong.
I've updated the code base again. You can download it on the FAQ at the site.
Comments
I made some test.
First : I am using Firefox.
Example if a write the word : "very" I do not get any suggestion.
If I click search and I reload the page and I try again to search "very" I get the suggestion.
Looks almost a cache effect.....strange.
Bye
Andrea
may I ask you way is that?
Thanks
Andrea
Nice feature.
Shouldn't it only show previous searches that returned one or more results?
- Mikkel
Mikkel: Maybe. :) That would be more work though. Right now I just log everything you search for.
Going to visit the Amazon wish list now. :)
Would that drive people away?
Noob question.. Can you change the autosuggest attribute to:
cfc:components.entries.init().getSearchHelp({cfautosuggestvalue})
And inside, the init sets up the DSN? Or:
cfc:components.entries.init(myDSN).getSearchHelp({cfautosuggestvalue})
Just to avoid having the proxy page? If the JavaScript is just doing a URL method call of the CFC, this wouldn't work..
Does that make sense?
Now I _am_ curious to see if the syntax will work. I'll give that a try.
As for your blog - I promise - I'm going to add an admin, and if you remind me later, I'll add your blog to it. (I had to remove one manually today, it got taken over by a spammer.)
I have tried several options to use autosuggest but I get always the error "exception thrown and not caught coldfusion" can you tell me what I do wrong
error "exception thrown and not caught"
I know I'll sound like a broken record, but the #1 tool in the world is Firebug. If you don't have it installed, install it, and see if it tells you something.
http://www.teamcapeholland2008.nl/cape.cfc?method=...
Which is returning an empty string. As a quick test, make your CFC ALWAYS return some static data.
I have put a download link on the page so you can see the code. It is an very simple cfc request at this moment and that doesnt work.
I have tried your example but that doesn't work either, the same error.
I don't use onRequestStart or onRequest ...
and I get result from the query see the page agian ..
http://www.teamcapeholland2008.nl/cape.cfc?method=...
And above thw WDDX, which is expected, there is a bunch of JS includes. You _sure_ you don't have an Application.cfc or cfm in the request anywhere?
in the application file. I have removed it and it works ....
So you can put not such tag in the application.cfm file :-)
Thnx Now I can sleep well :-)
BUT - I wouldn't recommend putting it in anyway. :)
Your WDDX result are all the places in Holland... :-)
Little country ... :-)
Thank you


very nice the aggregator.
I was on the site new and the autosuggestion looks not working.
Andrea