Using CF and AJAX to dynamically show and hide divs based on database values

Showing and hiding form and document elements on a page can be pretty useful when you're trying to walk a user through a process and you only want them to interact with controls that are geared towards to the task at hand.

There are a number of ways to do this but a very simple way is to nest your form controls inside of a div and then reference the div in your JavaScript code. Here's a simple example where I'm querying a database to figure out the behavior of how a page should act based on which option a user selects from a cfselect control.

First off, I've got a SQL Server table named PropertyDataType and it has a primary key named PropertyDataTypeCode (a simple varchar). This app will allow users to create custom properties that describe the configuration settings of various sophisticated machines in a factory. The machines can have different properties and the values of a machine setting or property will fall into 1 of 3 categories...

  • True or False (As in activate Flux Capacitor? Yes/No)
  • Numeric Ranges (Min/Max Values - like temperature setting between 38 and 42 degrees)
  • Custom Select Options (User Defined Drop Down List of choices)
So what we're essentially doing here is allowing the user to create a matrix of configuration choices specific to a machine. This is important because these machines will be used to plan and track production processes and each production run (or job) will require that a machine be configured in a specific manner to accomplish a job step in the production process.

Moving on, we also have a 3 other tables in play...

  • System (A simple table that uniquely identifies each machine)
  • SystemProperty (A table with a compound primary key that uniquely identifies one or more properties of a machine along with the property's custom setting values defined by our user)
  • SystemPropertySelector (A table that will hold user defined options created by our user should they elect to create a property that will be configured using a customizable drop down list)

So what we're trying to do is show or hide page elements based on what type of property the user is going to create. We give the user a list of property types that they can create by querying the aforementioned PropertyDataTypeCode table which gives us a list of property types and the behavior of our page. The possible behaviors are to show Min/Max controls, show a subgrid (a cfgrid that will look to our SystemPropertySelector table that holds the values of user defined drop down lists), or finally to show nothing (none - which would be the case if they chose to create a property that had a simple boolean answer).

The system.cfc method getPropertyDataType is shown below...

view plain print about
1<cffunction name="getPropertyDataType" access="public" returntype="query">
2        <cfargument name="propertyDataTypeCode" type="string" default="">
3        <cfquery name="qryPropertyDataType" datasource="#REQUEST.ds1#">
4            SELECT            PropertyDataTypeCode,
5                                Behavior
6            FROM                PropertyDataType
7            <cfif ARGUMENTS.propertyDataTypeCode NEQ "">
8                WHERE        PropertyDataTypeCode = <cfqueryparam cfsqltype="cf_sql_varchar" value="#ARGUMENTS.propertyDataTypeCode#">
9            </cfif>
10            ORDER BY        PropertyDataTypeCode
11        </cfquery>
12        <cfreturn qryPropertyDataType>
13    </cffunction>

This just simply gets our list of property types that a user can select from. Note that the following cfselect control references the query returned by this cfc. It also has an onChange action to call a js function named controlViewState.

view plain print about
1<cfselect name="propertyDataTypeCode" query="qryPropertyDataType" value="PropertyDataTypeCode" display="PropertyDataTypeCode" queryPosition="below" onChange="controlViewState()">
2                    <option value=""></option>
3                </cfselect>

The controlViewState function will call a remote access method in the system.cfc that will get the behavior of the page for us so that we can decided which document elements to show and hide...

view plain print about
1<script type="text/javascript">
2
3    errorHandler = function(code,msg) {
4        alert('Error ' + code + ': ' + msg);
5    }    
6
7    controlViewState = function(){
8        var propDataType = ColdFusion.getElementValue('propertyDataTypeCode', 'editSystemProperty', 'value');
9        var proxyControlView = new proxySystem();
10        proxyControlView.setCallbackHandler(controlViewStateCallback);
11        proxyControlView.setErrorHandler(errorHandler);
12        proxyControlView.getPropertyDataTypeBehavior(propDataType);
13    }
14
15    controlViewStateCallback = function(showHideAction){
16        switch(showHideAction){
17            case 'None':                
18                minMaxControls.style.display = 'none';
19                subGridControls.style.display = 'none';
20                break;
21            case 'ShowMinMax':
22                minMaxControls.style.display = 'block';
23                subGridControls.style.display = 'none';            
24                break;
25            case 'ShowSubGrid':
26                minMaxControls.style.display = 'none';
27                subGridControls.style.display = 'block';
28                ColdFusion.Grid.refresh('gridSystemPropertySelectors', true);
29                break;
30            default :
31                minMaxControls.style.display = 'none';
32                subGridControls.style.display = 'none';
33                break;
34        }
35    }
36
37</script>

The controlViewState function's callback handler is actually responsible for showing and hiding the named divs that hold our controls. So for instance if the user selects one of the following choices from our option list then we will dynamically show and hide divs based on what the Behavior column of the PropertyDataType table tells our code what to do...

So if we were to select Decimal as our Data Type then we our code would call up the database and figure out that we need to hide everything except for the controls responsible for showing Min/Max values.

If by chance we chose Selector then all controls are hidden and then we show the subGridControls div and refresh the cfgrid (this is done so that we can prepare the grid to be rendered properly - if not then it is distorted and the cfgridcolumns would be initially hidden to the end user).

The page layout is pretty simple but it is worth mentioning that you definitely don't want to forget the id attribute of your divs...

view plain print about
1<cfoutput>
2<body>
3    <cfform name="editSystemProperty" format="html">
4    <table>
5        <tr>
6            <td colspan="2" class="areaHeaderWhite">System Property</td>
7        </tr>
8        <tr>
9            <td class="fieldLabelWhite">System Property Code</td>
10            <td>
11                <cfinput type="text" maxlength="30" size="30" name="propertyCode" value="#propertyCode#">
12            </td>
13        </tr>
14        <tr>
15            <td class="fieldLabelWhite">Data Type</td>
16            <td>
17                <cfselect name="propertyDataTypeCode" query="qryPropertyDataType" value="PropertyDataTypeCode" display="PropertyDataTypeCode" queryPosition="below" onChange="controlViewState()">
18                    <option value=""></option>
19                </cfselect>
20            </td>
21        </tr>
22    </table>
23    <div id="minMaxControls" style="display:none;">
24        <table>
25            <tr>
26                <td class="fieldLabelWhite">Minimum Value</td>
27                <td>
28                    <cfinput type="text" name="minVal">
29                </td>
30                <td class="fieldLabelWhite">Maximum Value</td>
31                <td>
32                    <cfinput type="text" name="maxVal">
33                </td>
34            </tr>
35        </table>
36    </div>
37
38    <div id="subGridControls" style="display:none;">
39        <table>
40            <tr>
41                <td class="fieldLabelWhite">Selector Options</td>
42            </tr>
43            <tr>
44                <td>
45                    <cfgrid name="gridSystemPropertySelectors" format="html" selectmode="browse" striperows="yes" height="160" width="440"
46                    font="Verdana" fontsize="12" colheaderfontsize="12" selectcolor="##FF6600" colheaderfont="Verdana" pagesize="10"
47                    bind="cfc:#REQUEST.cfcDir#.system.getSystemPropertySelectorGrid(
48                                                                                                warehouseCode='
#warehouseCode#',
49                                                                                                systemCode='
#systemCode#',
50                                                                                                propertyCode={propertyCode},
51                                                                                                page={cfgridpage},
52                                                                                                 pageSize={cfgridpagesize},
53                                                                                                 gridSortColumn={cfgridsortcolumn},
54                                                                                                gridSortDir={cfgridsortdirection})"
>

55                        <cfgridcolumn name="WarehouseCode" display="no">
56                        <cfgridcolumn name="SystemCode" display="no">
57                        <cfgridcolumn name="PropertyCode" display="no">
58                        <cfgridcolumn name="SelectorValue" header="Selector Value" width="400">
59                    </cfgrid>
60                </td>
61            </tr>
62        </table>
63    </div>
64    </cfform>
65
66</body>
67</cfoutput>

Comments
coach bags outlet's Gravatar I really like your article, I support your point of view
# Posted By coach bags outlet | 6/18/10 6:15 AM
ciphone's Gravatar Hello!everyone!iphone is so expensive.so I like <a href=" www.efox-shop.com/index.php/cPath/5_35
" rel="nofollow"> Ciphone </a>. d^_^bIt is very interesting.I want to introduce <a href="http://www.efox-shop.com/"; rel="nofollow"> efox-shop</a> to you.
# Posted By ciphone | 7/30/10 11:19 PM
BlogCFC was created by Raymond Camden. This blog is running version 5.9.5.007. Contact Blog Owner