Raymond Camden's Blog Rss

Ask a Jedi: ColdFusion Autosuggest on 2 Columns

10

Posted in ColdFusion | Posted on 11-22-2009 | 3,952 views

Mike asks:

I'm working on a suggestion list for a search box, is it possible to query more than one column and return that from the binding CFC?

Absolutely. Remember, ColdFusion's autosuggest control doesn't care how you create the result, it just cares that you return an array of strings. How you create the array is up to you. When I first wrote back to Mike, I recommended simply running two queries. Then I remember that a union would work fine as well. Here is the example I created.

Ok, let's start on the front end:

view plain print about
1<cfform name="doesntmatter">
2
3<cfinput name="chosen" autoSuggest="cfc:test.getSuggest({cfautosuggestvalue})">
4
5</cfform>

It's truly unfortunate that ColdFusion doesn't make AJAX easier. Look at all the code above. All the messy JavaScript. I really wish ColdFusion did more to make this easier for me. It took me at least 35 seconds to write that code. Maybe even 40. I'm sure PHP does a better job here, so why can't ColdFusion? -sigh-

All kidding aside, you got to love the binding support in ColdFusion. Let's now take a look at the CFC's getSuggest method:

view plain print about
1<cffunction name="getSuggest" access="remote">
2    <cfargument name="suggest" type="string" required="true">
3    <cfset var search = "">
4    
5    <cfquery name="search" datasource="cfartgallery">
6    select art.artname as s
7    from art
8    where art.artname like <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.suggest#%">
9    union
10    select artists.lastname as s
11    from artists
12    where artists.lastname like <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.suggest#%">
13    </cfquery>
14    
15    <cfreturn listToArray(valueList(search.s))>    
16</cffunction>

As you can see, I search against two columns in two different tables. The result is a query with a column called S that contains the matches. Note: ColdFusion's autosuggest only allows you to do 'frontal' matches. So if you want "der" to match "Vader", you are out luck. That's why my search only uses a % at the end. I can return other matches but they won't show up.

Wait! I double checked the docs (always good to do so when you are absolutely sure you are right!) and turns out I was wrong. The cfinput tag has a "matchContains" attribute. It defaults to false. If true, then the autosuggest can match anywhere in the result.

So I changed the front end input to:

view plain print about
1<cfinput name="chosen" autoSuggest="cfc:test.getSuggest({cfautosuggestvalue})" matchcontains="true">

and changed my cfqueryparam (both of them) to:

view plain print about
1<cfqueryparam cfsqltype="cf_sql_varchar" value="%#arguments.suggest#%">

and it worked like a charm. I'm very happy to be wrong about that. Anyway, hopefully you see that the autosuggest can be built up anyway you want. I could even mix a cfdirectory query with a database query. Whatever your needs are - just ensure you've got an array at the end and your good to go.

Edit: Ok, so apparently, matchcontains is ColdFusion 9 only. I checked the ColdFusion 8 docs and it isn't there. Unfortunately, Adobe forgot to list this in the tag history, so I mistakenly assumed it was there in 8 and I missed it. I've blogged before about the updates and how you had to dig a bit to find the changes. Apparently this is one of those things didn't get added to the history/tag changed docs. So obviously the core request here - autosuggest against N columns - is possible in ColdFusion 8. The only thing my matchcontains does is allow you to match anywhere in the result. For ColdFusion 8, simply leave that attribute off, and ensure your query uses X%, not %X%.

Comments

[Add Comment] [Subscribe to Comments]

Hey Ray,
What if I wanted to takes this a step further and auto-fill form fields based upon what the user ultimately selects in "chosen"?
Can I return an array of multiple columns from that query and somehow autofill other fields on the page?
Unfortunately no. The auto select in CF is really meant to return just data for the drop down. This is trivial though in jQuery's autocomplete.
Ok cool, thanks Ray. I'll look into the jQuery autocomplete.
One thing I am trying to figure out is, is it possible to do an autosuggest but if you type in the last say...4 digits of a value, the result will still come up? Ex: The list of database values are very similar for the first 10 characters, but only the last 4 or 5 change. So I don't want the user to have to type in the first 10 to get the autosuggest to start working...does this make since?
NEVERMIND, matchcontains="true" worked like a charm....sorry for the bad post!
No worries Michael - thanks for posting what you found though as I'm sure others may have the same question.
anybody.. can help me to send source code about that.
Because it doesn't work, and i am newbie with coldfusion. Thanks anyway :)
Sorry - what doesn't work?
I have query his,
SELECT a.Name,c.Client FROM tAnggota a,tClient c WHERE   a.Name LIKE <cfqueryparam cfsqltype="cf_sql_varchar"value="%#ucase(arguments.search)%" /> AND c.Client = "#FORM.txtClient#" AND c.CodePK =a.CodeFK         Order by a.Name

and '#FORM.txtClient#' made error in my file.
The error is :
Error invoking CFC/dir/autosuggest.cfc : Element TXTXCLIENT is undefined in FORM. [enabling debugging by adding 'cfdebug' to your URL parameter to seemore information]
I hope you answer my question. Thanks
The error is pretty clear. That key does not exist in the form scope. This isn't a form post happening here - rather CF is grabbing a form field and passing the data itself.

[Add Comment] [Subscribe to Comments]