Ask Ben: Dynamic Form Field Population With jQuery

Hi Ben, Sorry for not clear enough with my question. Here is my scenerio. I have three input fields: 1) Empno as a combo box; 2) Ename as a text box, and 3) sal as text box.. Now i have all the empno's from the table in the combo box. AS the user selects one of employee number.. related data (ename and sal) should appear in the text boxes.. Can you please help me in this. Thanks.

What we have here is essentially a set of related form fields in which the value of two of them are directly dependent on the value of a third one. To get those first two fields to populate, we have to bind some sort of event listener to the master form field such that when it changes, it has the other two fields update as well. When figuring out where that dependent data comes from, we have two option: local data and remote data. Local data is going to be the fastest option, but depending on the volume of information, this might not be feasible. Remote data, retrieved with an AJAX call, will take a bit longer, but will ultimately make our form page much more light weight and flexible.

Because I am not sure where your data is coming from, I have taken the opportunity to write up a jQuery powered demo that features both data retrieval methods:

The code for this is going to be more complicated than it needs to be because it dynamically handles two different modes of data storage. But, even so, I think you'll see that I am breaking it down in ways that are very easy to understand:

When our document object model (DOM) is ready to be interacted with, I get a reference to the master select box and bind a "change" event handler to it. I am purposely defining the method of the change-handler outside of our bind so that we can leverage it in more than just one way. For example, by separating the event binding from the event handling, it allows us to execute the event handling manually and independently of the select box (NOTE: you can also manually trigger the change() event, but I'm just trying to show different ways of breaking the code up).

The UpdateFormFields() method, our event handler, checks to see if the AJAX checkbox was checked. If it was not checked, our method gets the field data from one method that delivers static data; if it was checked, our method gets the data from a different method that delivers AJAX-based data. You'll notice that both of these methods simply return data - they don't populate the form fields. The actual population of the form fields is left to another method altogether - PopulateFields().

By breaking all the pieces up, it gives us several advantages:

We never repeat ourselves because the individual pieces of functionality have been factored out.

Our code is easier to digest mentally because the parts are all bite-size.

Our code is easier to augment because there is low coupling between the parts.

In our GetAJAXValues() method, you'll notice that I'm doing something interesting - I'm storing the XHR (AJAX request) object as a property of the GetAJAXValues() function. In Javascript, functions are first-class citizens which means that they can be treated as real objects. And, objects can have properties. By storing the XHR object as a property of the method itself, it allows me to cohesively keep track of the current AJAX request without muddying up the global namespace.

The code that returns the data in the AJAX request is simply a ColdFusion version of the static data method:

<!--- Param the FORM variable. --->

<cfparam name="FORM.option" type="string" />

<!--- Check to see which return value we are using. --->

<cfswitch expression="#FORM.option#">

<cfcase value="opt1">

<cfset objReturn = {

Value1 = "AJAX Value 1 - Field 1",

Value2 = "AJAX Value 1 - Field 2"

} />

</cfcase>

<cfcase value="opt2">

<cfset objReturn = {

Value1 = "AJAX Value 2 - Field 1",

Value2 = "AJAX Value 2 - Field 2"

} />

</cfcase>

<cfdefaultcase>

<cfset objReturn = {

Value1 = "AJAX Default",

Value2 = "AJAX Default"

} />

</cfdefaultcase>

</cfswitch>

<!--- Return the serialized AJAX response. --->

<cfcontent

type="application/x-json"

variable="#ToBinary( ToBase64( SerializeJSON( objReturn ) ) )#"

/>

There's no one "right" way to execute this kind of dynamic form population. I'm using jQuery here because jQuery is the most amazing Javascript library ever. I'm also breaking up the code in a more distributed way for demonstration and explanation purposes; the same thing could have been easily accomplished in a more concise way. Even so, I hope that this demonstration has helped in some way.

And to avoid doing this:<code>Value1: objData.VALUE1</code>I have found that I can use this notation in ColdFusion:<code><cfset retVal["Status"] = 'Updated'></code>Instead of:<code><cfset retVal.Status = 'Updated'></code>

Name of a ColdFusion binary variable whose contents can be displayed by the browser, such as the contents of a chart generated by the cfchart tag or a PDF or Excel file retrieved by a cffile action="readBinary" tag. When you use this attribute, any other output on the current CFML page is ignored; only the contents of the file are sent to the client.

This is the reason why I convert it to Binary before passing it to Variable.

That said, I am fascinated that it works for you and I want to know more. What version of ColdFusion are you running? Are you on one of the other engines?

It has helper functions like formHash() which will either return a form as a hash of values, or populate a form based on hash values. So, you could just pass back a JSON record and use formHash() to update the form for you:

My apologies. I thought I had been using the VARIABLE attribute, but it turns out that I had run in to that error and did this instead:<pre><cfsetting enablecfoutputonly="true" /><!--- prevent unnecessary output ---> <snip - code removed><cfcontent type="application/json"><cfoutput>#serializeJSON(retVal)#</cfoutput></pre>

Seems nice. :) However, for the second part - I barely know what ColdFusion is. Can you post a sample output of your cold fusion script, so that I can see what kind of reply the AJAX function expects? That would be great.

Hey, Ben. When I asked you about this in an email this morning, I had not come across this yet. I think this was exactly what I was looking for. (I guess I just have to find the right "google" words). anyway, you can just disregard my email from this morning, although I still may not have "gotten" it by the time you email me back even, if you still do. Regardless, your help to the community is SO MUCH appreciated here. :-)

I just wanted to write an update. First of all, I'm sorry for bothering you about this when you already had a solution out there...when I did, I had not come across this post yet. Secondly, thank you so much! I have figured it out now, completely. You are so much help. I'm really glad I found this, and I will search harder the next time I come across a problem before asking for help. :-) Thanks.