Copy link to clipboard
Copied
Under normal circumstances, I can copy the content of the users's form field input into another field, just by simply javascripting (using onChange, and this.form.field.value).
In a CFInput field that does autosuggest (like in Ben Forta's simple examples), this doesn't work - 1) onChange behaves differently, and 2) the field value contains the original user search input, not the value that he chose from the suggested values.
How can I address the value that was chosen by the user?
Here's what I actually need to do:
I have a table with several columns and more than 70000 entries. There is a key column that users can choose from, and there is a text column that users can also choose from - either way should work. (Select fields don't work because there are too many values - it seems I have to use text fields with autosuggest.)
When the user chooses a numerical key value, the text field should be automatically filled with the corresponding text value. When the user instead chooses from the text values, the numerical key should automatically filled with the corresponding value. (This is what I tried to do with normal Javascript but it didn't work as explained above.)
To make things even more complicated, there are two more columns whose values should automatically be filled into the corresponding form fields as soon as the user has chosen a row.
I have no idea how to program this but I'm sure it is easily possible if one knows one's way around Ajax.
-Michael
Copy link to clipboard
Copied
You can use the bind attribute. It will override the current field entries. Could we see the code?
Copy link to clipboard
Copied
not much of code here that goes beyond Ben Forta's code. The CFC:
<cfcomponent output="false">
<cfset THIS.dsn="gmasql">
<!--- Lookup used for auto suggest --->
<cffunction name="lookupPZN" access="remote" returntype="string">
<cfargument name="search" type="any" required="false" default="">
<!--- Define variables --->
<cfset var data="">
<!--- Do search --->
<cfquery datasource="#THIS.dsn#" name="data">
SELECT PZN + ' ' + Handelsname as PZN
FROM pznHandelsname
WHERE PZN LIKE '#ARGUMENTS.search#%'
ORDER BY PZN
</cfquery>
<!--- And return it --->
<cfreturn ValueList(data.PZN)>
</cffunction>
<cffunction name="lookupHandelsname" access="remote" returntype="string">
<cfargument name="search" type="any" required="false" default="">
<!--- Define variables --->
<cfset var data="">
<!--- Do search --->
<cfquery datasource="#THIS.dsn#" name="data">
SELECT Handelsname + ' {' + PZN + '}' as Handelsname
FROM pznHandelsname
WHERE Handelsname LIKE '#ARGUMENTS.search#%'
ORDER BY Handelsname
</cfquery>
<!--- And return it --->
<cfreturn ValueList(data.Handelsname)>
</cffunction>
</cfcomponent>
The calling form fields:
<cfinput type="text" name="pmPZN"
value="#qry_datensatz.pmPZN#"
autosuggest="cfc:pzn.lookupPZN({cfautosuggestvalue})"
maxResultsDisplayed="50"
size="60">
<cfinput type="text" name="pmHandelsname"
value="#qry_datensatz.pmHandelsname#"
autosuggest="cfc:pzn.lookupHandelsname({cfautosuggestvalue})"
maxResultsDisplayed="50"
size="60"
>
Copy link to clipboard
Copied
How do you do the onChange? I miss that attribute and the Javascript that makes the change.
Copy link to clipboard
Copied
> How do you do the onChange? I miss that attribute and the Javascript that makes the change.
(argh) there is no onChange in the code because it doesn't work anyway, so there is no onChange in the code. (Please excuse me if I sound impatient.) I thought I had put my question so that everybody understands what goes wrong, but apparently not. The thread is "what is the value of an autosuggest input field?" - or better, "how can I retrieve, using Javascript or other methods, the user chosen value of an autosuggest field before sending a form?"
If I add onChange="alert(this.form.pmPZN.value);" to the CFInput, what happens is
1. it fires immediately when I click on one of the values that the autosuggest field suggests to me (the same applies to onBlur). Javascript seems to think that I have moved outside of the field when I click into the autosuggest value list,
2. the retrieved value of the field is still what I entered into it, not what I chose from the list.
Just try it and you can see at once what I mean.
-Michael
Copy link to clipboard
Copied
There is a lot to take in. If all you want is to generate autosuggest values, then get the functions to return arrays. Do this for example
<cffunction name="lookupPZN" access="remote" returntype="array">
<cfargument name="search" type="any" required="false" default="">
<!--- Define variables --->
<cfset var data="">
<!--- Do search --->
<cfquery datasource="#THIS.dsn#" name="data">
SELECT PZN + ' ' + Handelsname as PZN
FROM pznHandelsname
WHERE PZN LIKE '#ARGUMENTS.search#%'
ORDER BY PZN
</cfquery>
<!--- And return it --->
<cfreturn listToArray(ValueList(data.PZN))>
</cffunction>
Copy link to clipboard
Copied
hmm, interesting, but I don't see how this solves my problem - how can I find out the value that gets chosen by the user?
Copy link to clipboard
Copied
how can I find out the value that gets chosen by the user?
<cfinput type="submit" name="sbmt" value="Send">, or am I missing something?
Copy link to clipboard
Copied
yes, you are missing something :-), maybe I didn't explain it good enough.
I want to set one or two other fields in the form to a value that corresponds to the value that the user chooses, _before_ submit is clicked.
Imagine an autosuggest field which contains catalog numbers and names of 70000 pharmaceuticals (ordered by number), and another field containing the same, but ordered by name. The user can search for an entry either by searching for a number (using the first autosuggest field), or by searching for a name (using the second autosuggest field). When he searches by number, clicking on suggested values from the number field should immediately fill the second field with the corresponding name, and vice versa, before submit is clicked.
-Michael
Copy link to clipboard
Copied
Is this still open?
Copy link to clipboard
Copied
yes, I'm still looking for an answer. I've found a workaround but I'd rather find a real solution.
-Michael
Copy link to clipboard
Copied
I have taken some time to read all your posts, in some detail this time. I hope I now better understand what your intention is.
First, it is my opinion that Coldfusion cannot do what you wish it to do. You wish to be able to enter a number, say, 1, in one form field, and for that to automatically generate a string in a second field. In either case, you pass cfautosuggestvalue in the binding function. It is apparent that what you want is a combination of binding and autosuggest. That is not possible in Coldfusion, at least, not yet.
The cfautosuggestvalue implies that Coldfusion will expect the user to enter a letter, if the argument of the binding function is of string type, or a digit, if the function expects an integer argument. However, what you want is different.
You want to ensure the string field can pass an argument to the integer field's binding function. Likewise, you want the integer field to be able to pass an argument to the string field's binding function. One way to achieve this is for each function to have at least 2 arguments.
Here is an example. The files selectItem.cfm and Medication.cfc are in the same directory.
ItemNumbers starting with 1 are pain-relievers. ItemNumbers starting with 2 are antibiotics.
selectItem.cfm
============
<cfif isDefined("form.item")>
<cfdump var="#form#">
</cfif>
<cfform name="medform" action="#cgi.SCRIPT_NAME#">
Item name: <cfinput autosuggest="cfc:Medication.getItem({cfautosuggestvalue}, {itemNumber})" autosuggestminlength="1" type="text" name="item" size="50" typeahead="yes">
<br>
Item number:<cfinput autosuggest="cfc:Medication.getItemNumber({cfautosuggestvalue}, {item})" autosuggestminlength="1" type="text" name="itemNumber" size="50" typeahead="yes" value="11">
<br>
<cfinput type="submit" name="sbmt" value="Get item">
</cfform>
Medication.cfc
============
<cfcomponent>
<cffunction name="getItem" access="remote" returntype="array">
<cfargument name="suggestedValue" required="true" type="string">
<cfargument name="itemNumber" required="no" type="numeric">
<cfset var item = arrayNew(1)>
<!--- first set: pain relief --->
<cfif arguments.itemNumber is 11 or arguments.itemNumber is 14 or arguments.itemNumber is 17>
<cfset item[1]="Aspirin">
<cfset item[2]="Ibuprofen">
<cfset item[3]="Paracetamol">
<cfelseif arguments.itemNumber is 22 or arguments.itemNumber is 23 or arguments.itemNumber is 28>
<!--- second set: antibiotics --->
<cfset item[1]="Amoxicillin">
<cfset item[2]="Penicillin">
<cfset item[3]="Tetracycline">
</cfif>
<cfreturn item>
</cffunction>
<cffunction name="getItemNumber" access="remote" returntype="array">
<cfargument name="suggestedValue" required="true" type="numeric">
<cfargument name="item" required="no" type="string" default="Aspirin">
<cfset var itemNumber = arrayNew(1)>
<cfif arguments.item is "Aspirin" or arguments.item is "Ibuprofen" or arguments.item is "Paracetamol">
<cfset itemNumber[1]=11>
<cfset itemNumber[2]=14>
<cfset itemNumber[3]=17>
<cfelseif arguments.item is "Amoxicillin" or arguments.item is "Penicillin" or arguments.item is "Tetracycline">
<cfset itemNumber[1]=22>
<cfset itemNumber[2]=23>
<cfset itemNumber[3]=28>
</cfif>
<cfreturn itemNumber>
</cffunction>
</cfcomponent>
Copy link to clipboard
Copied
thanks for your detailed reply BKBK, much appreciated!
The thing is, I don't really understand how binding and autosuggest work, and frankly, I don't have the time at the moment to learn the Ajax intricacies because I have to quickly come up with this complex database application, and I find myself in a situation where I am forced to use autosuggest because I can't see any other way to have the user choose from 70000+ values in an elegant way. But I still don't understand how it works - I don't even understand how to apply what you suggested to solve my problem.
On a very basic level: As someone who only knows HTML, simple Javascript, and ColdFusion, I still wonder about this: when I choose a value from an autosuggest field - I click on one of the suggested values, and that value is then displayed in the form field -, where is that value stored at that moment, and is it possible to access it there using traditional Javascript syntax? something like, document.forms.formname.fieldname.value - that's what it used to be? It must be stored somewhere, because when I submit the form, it comes across to the next page as if it had been a regular form field value. But before I submit the page, it behaves different from a regular form field - it is apparently not accessible to Javascript like a simple form field is. Or is it just a matter of another syntax?
And even if I knew a JS syntax that would access the chosen value, it seems I couldn't use it because choosing an autosuggest value doesn't trigger the onChange event ...
best,
-Michael
Copy link to clipboard
Copied
I still wonder about this: when I choose a value from an autosuggest field - I click on one of the suggested values, and that value is then displayed in the form field -, where is that value stored at that moment, and is it possible to access it there using traditional Javascript syntax? something like, document.forms.formname.fieldname.value - that's what it used to be?
Yes.
Do some tests. Use the code I gave, and store the two files in the same directory. Add the following code at the beginning of selectItem.cfm.
<script type="text/javascript">
function whatsUp() {
alert("OnChange occurred. Current field value: " + document.medform.item.value)
}
function show() {
alert(document.medform.item.value)
}
</script>
Then modify the item and submit fields by adding onChange and onClick, as follows:
<cfinput autosuggest="cfc:medication.getItem({cfautosuggestvalue}, {itemNumber})" autosuggestminlength="1" type="text" name="item" size="50" typeahead="yes" onChange="whatsUp()">
<cfinput type="submit" name="sbmt" value="Get item" onClick="show()">
You need nothing more. This is sufficient to answer 2 of your questions, namely
1) Does the onChange event fire after the user selects an autosuggested value?
2) Can one use Javascript to display the autosuggested field's value.
Before you proceed, the answer to both questions is Yes. See for yourself.
Open the page selectItem.cfm in the browser. You should get a form. You should see the default item number 11 displayed.
Type the letter A in the first(blank) form field. Coldfusion should autosuggest the word Aspirin. Click on the word to select it.
The onChange event will not fire, because there has been no change in the field value. Now, change the entry from Aspirin to Aspirin tablet, and point the mouse out of the field. The onChange event should then be triggered.
On to the next test. Click on the button to Get item. You should get an alert-box, displaying Aspirin, or Aspirin tablet, if that is what the field currently contains.
It[the field value] must be stored somewhere
Yes, in the user's browser.
I submit the form, it comes across to the next page as if it had been a regular form field value. But before I submit the page, it behaves different from a regular form field - it is apparently not accessible to Javascript like a simple form field is.
The field is accessible to Javascript. That is why Aspirin (or Aspirin tablet) could be displayed.
I don't even understand how to apply what you suggested to solve my problem.
Then forget it. Close that chapter. Let's start all over, with what you understand. Expect me back in a moment.
Copy link to clipboard
Copied
Given a list of 70000 items, I think your choice of autosuggest as display strategy is good. But then, you have to make some choices to enable you to break a big problem down to small parts. Here are some strategies you might want to consider:
1) Select items by name or by number, however, without any binding between the two.
2) Restrict the number of items in the autosuggest list to, say, 30 or less.
You have more or less already done 1). I am assuming that PZN is a number and Handelsname a name. If so, just modify the functions in your CFC to return an array(See my earlier suggestion). Also, remove the value attribute from the cfinput tags. Your CFC and form are then ready to go!
Now comes your point of worry. The way things stand, there is every probability that Coldfusion might show the user 3000 autosuggest values the moment he enters the letter A in the name field. The same might happen if he enters 1 in the number field. You can obtain the solution, that is, 2), by experimentation.
The solution 2) relies on the 3 cfinput attributes autosuggestMinLength, autosuggestBindDelay and maxResultsDisplayed. The documentation says:
autosuggestMinLength: The minimum number of characters required in the text box before invoking a bind expression to return items for suggestion. (Default value = 1)
autosuggestBindDelay: A nonzero integer that specifies the minimum time between autosuggest bind expression invocations, in seconds. This value also specifies the delay from when the user first enters a minimum-length entry in the field until the suggestion box appears. Use this attribute to limit the number of requests that are sent to the server when a user types.
(Default value = 0.5 seconds)
maxResultsDisplayed: The maximum number suggestions to display in the autosuggest list.(Default value = 10)
That is where experimentation comes in. You already know about maxResultsDisplayed. That's one down, two to go.
Obviously, the higher the value of autosuggestMinLength, the more specific the value in the query's like-clause, hence the more efficient the autosuggest selection. Also, the smaller the autosuggestMinLength, the larger the result set to be returned by the query, hence the need for a larger autosuggestBindDelay. And so on.
<cfinput type="text" name="pmPZN"
autosuggest="cfc:pzn.lookupPZN({cfautosuggestvalue})"
autosuggestMinLength="2"
autosuggestBindDelay="1"
maxResultsDisplayed="30"
size="60">
<cfinput type="text" name="pmHandelsname"
autosuggest="cfc:pzn.lookupHandelsname({cfautosuggestvalue})"
autosuggestMinLength="3"
autosuggestBindDelay="2"
autosuggestMinLength="30"
size="60">
Copy link to clipboard
Copied
I have the same need for reading the 'Clicked' value of an Autosuggest(ed) row/table/list and process it's value further and populating several other form fields with the processed result. To be exact; I want to populate a 'customer form' with more than twenty different fields WITHOUT submitting any other form.
ColdFusion uses libraries from Yahoo, and in this case "autocomplete-min.js" located deep in the CFIDE directory.
In the /CFIDE/scripts/ajax/yui/autocomplete directory to be exact.
At line 44 (in my CF9 installation) it says:
YAHOO.widget.AutoComplete.prototype._sendQuery=function(sQuery){if(this.minQueryLength==-1){this._toggleContainer(false);return;}
At line 87 it says:
YAHOO.widget.AutoComplete.prototype._updateValue=function(oItem)
You may use these results to hack your own 'middleware' using the itemSelectEvent.
The oItem will contain the chosen value that will be set to the _updateValue and then sent back to ColdFusion's <CFINPUT> form field as a new Value.
I can do another post in this forum when/if I succeed in my project.
/Roger
// Nothing is impossible - It's just a matter of time and energy.
Copy link to clipboard
Copied
Take a look at this page. It is for 9.0.1, but I think it is exactly what you are looking for.
http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSd160b5fdf5100e8f-4439fdac128193edfd6-7f5e.html
I was trying to do something similar to you. I wanted to have someone typing in a serial number (there are thousands and thousands) be able to drill down and pick a specific one. When they selected the serial number, then I wanted to fire off some other events via ajax. I could never get the onChange event to fire.
I modified the example selctItem.cfm above to incorporate the page above. When you select something from the top item field, it will update the new middle field. Now it works pretty slick.
Here it is:
<html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<head>
<cfajaximport tags="cfinput-autosuggest">
<script>
var init = function()
{
autosuggestobj = ColdFusion.Autosuggest.getAutosuggestObject('item');
autosuggestobj.itemSelectEvent.subscribe(foo);
alert("attaching item to foo");
}
var foo = function(event,args)
{
var msg = "";
msg = msg + "Event: " + event + "\n\n";
msg = msg + "Selected Item: " + args[2] + "\n\n";
msg = msg + "Index: " + args[1]._nItemIndex + "\n\n";
alert(msg);
document.medform.stub.value = args[2];
}
function whatsUp() {
alert("OnChange occurred. Current field value: " + document.medform.item.value)
}
function show() {
alert(document.medform.item.value)
}
</script>
</head>
<body>
<h3>Attaching an event handler to the autosuggest object</h3>
<cfform name="medform" action="#cgi.SCRIPT_NAME#">
<table cellpadding="0" cellspacing="0" border="0">
<tr>
<td>Item Name</td>
<td><cfinput autosuggest="cfc:medication.getItem({cfautosuggestvalue}, {itemNumber})" autosuggestminlength="1" type="text" name="item" size="50" typeahead="yes" onChange="whatsUp()"></td>
</tr>
<tr>
<td>Test</td>
<td><cfinput name="stub" value="" onChange="whatsUp()"></td>
</tr>
<tr>
<td>Item Number</td>
<td><cfinput autosuggest="cfc:Medication.getItemNumber({cfautosuggestvalue}, {item})" autosuggestminlength="1" type="text" name="itemNumber" size="50" typeahead="yes" value="11"></td>
</tr>
<tr>
<td> <cfinput type="submit" name="sbmt" value="Get item" onClick="show()"></td>
</tr>
</table>
</cfform>
<cfset ajaxOnLoad("init")>
</body>
</html>
Copy link to clipboard
Copied
i do not know