Skip navigation
Currently Being Moderated

what's the value of an autosuggest input field?

Dec 1, 2009 3:21 AM

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

 
Replies
  • Currently Being Moderated
    Dec 4, 2009 2:27 AM   in reply to veloopity

    You can use the bind attribute. It will override the current field entries. Could we see the code?

     
    |
    Mark as:
  • Currently Being Moderated
    Dec 14, 2009 11:15 AM   in reply to veloopity

    How do you do the onChange? I miss that attribute and the Javascript that makes the change.

     
    |
    Mark as:
  • Currently Being Moderated
    Dec 14, 2009 12:55 PM   in reply to veloopity

    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>

     
    |
    Mark as:
  • Currently Being Moderated
    Dec 15, 2009 10:16 PM   in reply to veloopity
    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?

     
    |
    Mark as:
  • Currently Being Moderated
    Dec 23, 2009 8:28 AM   in reply to veloopity

    Is this still open?

     
    |
    Mark as:
  • Currently Being Moderated
    Dec 23, 2009 12:22 PM   in reply to veloopity

    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>

     
    |
    Mark as:
  • Currently Being Moderated
    Dec 24, 2009 2:47 AM   in reply to veloopity
    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.

     
    |
    Mark as:
  • Currently Being Moderated
    Dec 24, 2009 3:48 AM   in reply to veloopity

    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">

     
    |
    Mark as:
  • Currently Being Moderated
    Calculating status...
    Feb 10, 2011 1:22 AM   in reply to veloopity

    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.

     
    |
    Mark as:
  • Currently Being Moderated
    Mar 15, 2012 1:45 PM   in reply to veloopity

    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>
     
    |
    Mark as:
  • Currently Being Moderated
    Mar 20, 2012 9:30 PM   in reply to veloopity

    i do not know

     
    |
    Mark as:

More Like This

  • Retrieving data ...

Bookmarked By (0)

Answers + Points = Status

  • 10 points awarded for Correct Answers
  • 5 points awarded for Helpful Answers
  • 10,000+ points
  • 1,001-10,000 points
  • 501-1,000 points
  • 5-500 points