On my current assignment, a problem has cropped up three times since the middle of last year. An Active Server Page (ASP) contains a Design Time Control (DTC) list box whose contents are dependent upon another DTC list box’s selection. For example, the shipper is dependent on the source factory. Or here's an even more intricate example: The shipper is dependent on the source factory, which is dependent on the customer. These dependencies can cause the relationships between list boxes to quickly get complex.
Updating the DTC list box
The first try was golden. The solution worked perfectly. Selecting an option from the first list box caused the options in the second to be changed. I played with it for several minutes feeling very pleased with myself. Then, I clicked the Submit button. The server side treated the dependent DTC list box as if it were still empty. Not the functionality that I expected.
Being under the usual tight deadline, I briefly considered a band-aid solution—adding another hidden input box to handle the selection made in the dependent DTC list box. I quickly discarded that solution because it was overly complex to handle. What was needed was a solution with at most one server-side and one client-side element.
A better solution
My search for a better solution began with a look at the generated HTML. It was obvious that something was missed on the client-side, because of the failure of what should have been a simple change.
Examining the HTML generated by IIS revealed something very interesting: Each DTC has a hidden input box associated with it. DTCs are like icebergs—only a fraction is visible above the water line. I made the mistake of assuming that the HTML list box that was visible was all there was and that changing the visible object was sufficient.
The ASP engine employs these hidden input boxes to maintain state so that selections will be retained if the page is reloaded. The list box DTCs mirror the options available in the associated list box. This was the problem with my code: It did only part of the job. It is necessary to update the list box DTC below the water line. Armed with this knowledge, I was ready to take another shot at updating a DTC list box on the client side.
More ways to extend DTC
To find how you can further extend DTCs, check out "Client-side sortable data grids can reduce server traffic."
Changing a DTC list box option
Updating the value of the hidden input box isn’t a problem once the format of the input box’s name is known. The name of the hidden input box is always an underscore (_), followed by the name the DTC list box, followed by another underscore and the word state, in lowercase. Let’s assume that the DTC list box’s name is plugh. This would make the hidden input box’s name _plugh_state. Knowing this allows us to access the input box’s value and change it.
The value of a hidden input box corresponds to the associated list box, so if the first option is blank, the first part of the value is &t0=. If the second option is red, the value is &t0=&t1=red, and so on, for each option. To reduce bandwidth, I used regular expressions to modify my hidden options into the correct format for the hidden input box value.
This leaves only one task: preserving the dependent DTC list box’s onchange event. That was more difficult than it sounds but was not insurmountable. It was necessary to hang on to the original onchange() event handler and set the event handler for the updated DTC list box to the original event handler.
Using the subroutine and the function
The server-side function, buildDropDown, requires four parameters:
- The origin DTC list box that has a DTC list box dependent upon it
- The dependent DTC list box
- An ADO connection string
- A SQL command to populate the dependent list box
The format of the SQL is as follows:
WHERE origin_value = 'xxxxxxxx'
The “xxxxxxxx” acts as a placeholder; the origin DTC list box’s option values are substituted to retrieve the information required to build the hidden input boxes. With this in mind, the format to invoke this subroutine is:
document.thisForm.origin.onchange = new Function('updateDropDown(document.thisForm.origin, document.thisForm.dependent)');
The above code snippet can be included either in the page’s onload event handler or in a function invoked by the onload event handler.
Extending the flexibility
Microsoft’s DTCs offer a quick and easy way to build ASPs, but the process is often at the expense of flexibility. By examining the HTML generated by ASP, it is usually possible to extend the DTCs to give your applications a more polished look and feel.
Do you want more DTC articles? Share your opinions or post your comments below.