This is a question I get about once a month. Is it possible to use an autosuggest that returns complex data? What I mean is - I want to be able to start typing into a text field, see a list of matching names come up, but when I pick one, I need to know both the name value and the ID related to the name. So for example, imagine this data:
ID | Name |
---|---|
1 | Paris Hilton |
2 | Darth Vader |
3 | Victor Newman |
If I type "v" and see Victor Newman pop up, when I select him I need to know that his ID was 3.
As far as I know this isn't possible with both Spry and ColdFusion 8's autosuggest. Both demand you return simple values to populate the suggestions.
You could do a lookup based on the name. So once you get the name, do another Ajax request to translate "Victor Newman" to 3. You can probably guess the problem with this. If there are two Victor Newmans, than what ID would you return? You could return names along with a middle initial, but that simply reduces the problem. It doesn't fix it. Depending on how complex you want to get though - you could do your Ajax request and when you see more than one result returned, prompt the user to pick the one they meant.
Has anyone else solved this problem? I'm thinking there has to be a better solution.
Archived Comments
I've done this by bind a cfselect to an input field. So the user types in the input field and the values appear in the select. You can set the size of the select to 5 or 10 if you want people to see it.
So I'm confused. Is your comment specifically talking about the issue of linking one name to N results with the same name?
I've never used it with ColdFusion 8 or Spry, but normally I in my json or whatever feeds the values to the type suggest I will create lists as my values of some sort, wither by number of characters or delimiters: "23|John Doe". Thats pretty easy to decode in any server side language.
The multiple "Victor Newman" problem may be a moot point. If two "Victor Newman"s show up in your auto-suggest list, how is your user supposed to differentiate between them? Seems like there's a more critical user interface problem that underlies that hypothetical duplicate label problem... ie, you shouldn't be showing duplicates in the list in the first place (assuming the list is an identity selection and not a search term selection).
Granted, the secondary lookup of the selected label is clunky, but it does seem like a valid workaround.
This should be pretty simple to do if you can capture or wire your own event that gets triggered after you do the select. Something like:
function afterSelect() {
// alert the value of the selected element
alert(document.getElementById(this.id).value));
}
The above has not been tested but it should give you an idea on how to implement.
@Ray:
This is how it would work:
<input type="text" name="lookup" id="lookup"><br />
<cfselect name="userID" id="userID"
bind="url:/index.cfm?
event=user.lookup={lookup@keyup}"
display="userName"
value="userID"
bindOnLoad="false" />
As the user types in the lookup field, it fires off a request to the server which returns a json-ed query to the select which puts the IDs and names in the right place. User then picks the correct user name and when submitting the form returns the ID.
Ah so technically you aren't doing a traditional autosuggest at all.
Yeah.
Is autosuggest old enough to have a traditional version?! Haha.
This is easy with jQuery and Jorn's excellent Autocomplete plugin: (http://bassistance.de/jquer...
I routinely use this and then use jQuery to populate a hidden field with the user ID.
Thanks for sharing, Jim.
Is there anything jQuery can't do? ;)
It currently cant bring Coffee to my desk, but I've taken to calling my assistant Jquery to bridge that gap.
I ran into this when autosuggesting on multiple fields and displaying multiple fields...for instance: auto suggest a POC at specific location... I let the user type in the location or the first or last name of the poc and it returns the POC, Company, and City and lastly ID into the autosuggest. I append ID: at the end of it, then I parse out the ID to run another ajax query and load the complete POC data into display with other contact info and pass the ID as a hidden field.
This is possible with Spry. Display the autosuggest in a table:
<div id="autosuggest">
<span id="SupplierName"><input type="text" name="SupplierName" id="SupplierName" /></span>
<div id="SupplierMenu" spry:region="dsSuppliers">
<table>
<tr>
<th>Supplier ID</th>
<th>Supplier Name</th>
</tr>
<tr spry:repeat="dsSuppliers" spry:suggest="{SUPPLIERID}|{SUPPLIERNAME}">
<td>{SUPPLIERID}</td>
<td>{SUPPLIERNAME}</td>
</tr>
</table>
</div>
</div>
Tweak the Spry.Widget.AutoSuggest.prototype.setValue function in SpryAutoSuggest.js file (Spry 1.6.1 line 178)to break the string into an array of strings and populate the form:
Spry.Widget.AutoSuggest.prototype.setValue = function(str)
{
if (!this.textElement)
return;
this.textElement.value = str;
var myArray = str.split(/\|/);
document.form.SupplierID.value=myArray[0];
this.textElement.value=myArray[1];
this.showSuggestions(false);
};
To be fair Stich - I don't think modifying Spry to make it work is the same as 'possible' with Spry. ;)
I do this by getting an array from my query,
eg <cfloop query="get_staff">
<cfset my_staff_array = ArrayAppend(staff_array, "#contact_first_name# #contact_surname# #contact_id#")>
</cfloop>
use ArrayToList to change it to a list, which cfautosuggest accepts.
<cfset staff_name_list = ArrayToList(staff_array,",")>
Then on my action page, get the id field
<cfset contact_id = ListLast(staff_name_list, " ")>
This seems to work - not sure how efficient it is
Seamus
I wrestled with this issue for a while. This is what i came up with. I wanted to populate a hidden "personID" field when they selected from a "personName" cfselect. Instead, I populated a second cfselect with a bind attribute just like the clasic city/state example. If the "personID" cfselect calls a cfc that only returns one record, then it can work the same as the hidden input item that we originally wanted. finally you just have to use css to hide the second cfselect. My code is a little messy still, or else I would post it.
Hi Seamus -
I've added the ArrayToList function to my CFC. I am still trying to grab the ID from my list of clients.
I've used your recommendation on my action page of grabbing the ID, but I'm having no luck. Could you elaborate on how you accomplish this?
Thanks,
Adam
I know this isn't the best approach, but it works. My return values from the CFC are in the format of:
#name# <span style='display:none'>#id#</span>
Then in my JavaScript, I strip the <span></span> from the result and put the id in a hidden field.