ColdFusion 9.0 Resources |
Binding data to form fieldsMany ColdFusion Ajax features use binding to provide dynamic interactivity based on user input or changing data. When you use binding, a bind expression gets evaluated, and the display gets updated based on new data each time a specific event (onChange by default) occurs on a form control field specified by a bind parameter. This way, the value of the tag that specifies the bind expression, and the display, get updated dynamically based on changing information, including user-entered form data. When you use binding the page contents updates, but the entire page is not refreshed. Note: When a bound window is not visible, or a tab
is not selected, its contents is not updated when the controls it
is bound to change. When the tab or window is made visible, it is
updated only if events have been received from the bound controls
while the control was not visible.
Depending on the specific ColdFusion tag, a bind expression uses bind parameter values directly or passes bind parameter values as parameters to a CFC function, a JavaScript function, or an HTTP request and uses the function or request response to update the page. Use the following as the data source for a bind expression:
Note: You cannot use a bind expression to bind to
controls in a dynamically loaded region. For example, you cannot
bind from a control on one page to a control in a layout area on
that page if the cflayoutarea tag uses a source attribute
for its contents. However, a dynamically loaded region binds to
controls on the page that loads it, so the file specified by the source attribute
uses bind expressions that specify controls on the page that contains
the cflayoutarea tag.
The results of the bind expression determine the value of the tag that uses the expression. For example, if you specify a URL in a bind expression as the source attribute of a cfwindow control, the page specified by the URL must return the full contents of the window. For more examples, see Using Ajax User Interface Components and Features and the reference pages for controls that support binding. Using bind expressionsTo specify a bind expression, use one of the following formats:
In formats 1-4 the parameters normally include one or more bind parameters. The following table lists the tag attributes that support bind expressions and the formats each use:
The following examples show some of these uses: bind="cfc:myapp.bookorder.getChoices({book})" source="/myApp/innerSource/cityWindow.cfm?cityname={inputForm:city} In these examples, {book} and {inputForm:city} specify bind parameters that dynamically get data from the book and city controls, and the city control is in the inputForm form. If a bind attribute specifies a page that defines JavaScript functions, the function definitions on that page must have the following format: functionName = function(arguments) {function body} Function definitions that use the following format may not work: function functionName (arguments) {function body} However, Adobe recommends that you include all custom JavaScript in external JavaScript files and import them on the application’s main page, and not write them inline in code that you get using the source attribute. Imported pages do not have this function definition format restriction. Specifying bind parametersA bind parameter specifies a form control value or other attribute, as in the following example: bind="cfc:myapplication.bookSearch.getStores({form1:bookTitle})" In this example, the bind parameter is form1:bookTitle and specifies the value attribute of the bookTitle field of the form1 form. Bind parameters have either of the following formats: {[formName:]controlName[.attributeName][@event]} {SpryDataSetName.fieldName} The brackets ([]) indicate optional contents and are not part of the parameter. Note: To include a literal brace character in a bind
expression, escape the character with a backslash, as \{, \}.
The formname valueThe formname entry identifies the form that contains the control you are binding to. Specify a form name if multiple forms contain bind targets with the same names. To specify the form name, start the bind expression with the form’s id attribute the name attribute if you did not specify an id attribute, and follow it with a colon (:). To specify the book control that is in a form named inputForm, for example, use the following format: bind="cfc:myapp.bookorder.getChoices({inputForm:book})" The controlName valueTo bind to a form field, the controlName value must be the value of the id or name attribute of the form control to which you are binding. If a control has both an id and a name attribute, use either value. You can bind to any ColdFusion form control, including cfgrid and cftree. You cannot bind to values in other ColdFusion tags, such as cftable. To bind to a Spry data set, specify the data set name in this part of the bind parameter. You can bind to multiple radio buttons or check boxes by giving them the same name value. If all the radio buttons in a radio button group have the same name value, the bind parameter represents the selected button. If multiple check boxes have the same name value, the bind parameter represents the values of the selected controls in a comma-delimited list. If you also specify a unique id attribute for each check box or radio button, specify an HTML label tag for each button or check box and use the id value in the for attribute; in this case, users select items by clicking the label, not just the button or box. If a cfselect control supports multiple selections, the bind expression returns the information about the selected items in a comma-delimited list. You can bind only to controls that are available in the DOM tree when the bind is registered. Binds are registered when the page with the bind expression loads, either in the browser window or in a container tag. As a result, if you have two cfdiv, cflayoutarea, cfpod, or cfwindow containers that you load by using a source (or for cfdiv tag, bind) attribute, you cannot bind controls in one container to controls in the other, because one container cannot be assured that the other is loaded when it loads. Similarly, elements on the main page cannot bind to elements on a dynamically loaded container. To prevent this problem, define the bind target in line on the main page, instead of using a source or bind attribute to retrieve the markup that contains the bind target. In other words, the “master” form with fields that serve as sources of bind expressions is loaded statically (on the main page), and the “child” controls that depend on the data are loaded dynamically, on a page that is specified in a source or bind attribute. The attributeName valueWhen you bind to a form control, by default, the bind expression represents the value attribute of the specified control. If the bind target is a cfselect tag, the bind expression represents a comma delimited list of the values of the selected items. To bind to a different attribute, follow the control name or id with a period (.) and the attribute name. To pass the checked attribute of a checkbox cfinput tag as a CFC parameter, for example, use an expression such as the following: bind="cfc:myapp.bookorder.useStatus({myForm:approved.checked"@click}" Note: You can bind to the display text of a select box,
instead of the value, by specifying an attribute name of innerHTML.
Note: When you bind to a check box, use the @click event
specifier to ensure that the bind expression is triggered in Internet
Explorer when the user selects or deselects the check box, not when
the box loses focus.
Grids and trees do not have default bind attributes.
To bind to a Spry data set element or attribute, use standard Spry path notation. For example, specify an element name. The event valueBy default, the bind expression function executes each time the control specified in the bind parameter has an onChange event. To trigger updates on a different JavaScript event, end the bind expression with an at sign (@) and the event name, without the “on” prefix. The following code, for example, executes the getChoices CFC each time the user presses the mouse button while the pointer is over the book control: bind="cfc:myapp.bookorder.getChoices({inputForm:book@mousedown})" Note: To bind to a cfinput control
with type attribute of button,
specify a bind event setting, such as click. The change event
is the default event has no effect.
When you bind to a Spry data set, do not specify an event. The expression is evaluated when the selected row changes in the data set, or when the data set reloads with new data. You can also specify that a specific bind parameter never triggers bind expression reevaluation, by specifying @none as the event. This is useful, for example, if a bind expression uses multiple bind parameters binding to different form fields, and you want the bind expression to trigger changes only when one of the fields changes, not when the others change. In this case, you would specify @none for the remaining fields, so events from those fields would not trigger the bind. The following code shows this use: bind="cfc:books.getinfo({iForm:book}, {iForm:author@none})" The @none event specifier is also useful when used with autosuggest text inputs, trees and grids, as follows:
Using CFC functions in bind expressionsAs with JavaScript functions, you pass arguments to a CFC function specified in a bind expression positionally. When you do this, the argument names in a CFC function definition do not have to be the same as the bind parameter names, but the arguments in the bind expression must be in the same order as the arguments in the CFC function definition. Alternatively, you pass named CFC function arguments. Then, the bind expression and CFC function must use the same names for the arguments, and the function does not have to define the arguments in the same order as they are passed. To specify argument names in a bind expression, use a format such as the following, which uses two named parameters, arg1 and arg2: bind="cfc:mycfc.myfunction(arg1={myform:myfield1},arg2={myform:myfield2})" Using binding in control attributesWhen you use direct binding you specify a bind expression in a ColdFusion form or display control attribute. In the simplest, form of binding you use form fields, such as a name field, to fill other fields, such as an e-mail field, as the following example. shows. When you enter a name or domain and tab to click in another field, the name is added to the e-mail field. <html> <head> </head> <body> <cfform name="mycfform"> First Name: <cfinput type="text" name="firstname" value=""><br> Last Name: <cfinput type="text" name="lastname" value=""><br> Domain: <cfinput type="text" name="domain" value=""><br> E-mail: <cfinput type="text" name="email1" size="30" bind="{firstname}.{lastname}@{domain}"> </cfform> </body> </html> The following example shows the results of binding to radio buttons and check boxes with the same name attribute but different id attributes. Notice that because each control has a separate id value that is used in the label tags, you click the labels to select and deselect the controls. <html> <head> </head> <body> <cfform name="myform"> Pick one: <cfinput id="pickers1" name="pickone" type="radio" value="Apples"> <label for="pickers1">Apples</label> <cfinput id="pickers2" name="pickone" type="radio" value="Oranges"> <label for="pickers2">Oranges</label> <cfinput id="pickers3" name="pickone" type="radio" value="Mangoes"> <label for="pickers3">Mangoes</label> <br> <cfinput name="pickone-selected" bind="{pickone}"><br /> <br /> Pick as many as you like: <cfinput id="pickers4" name="pickmany" type="checkbox" value="Apples"> <label for="pickers4">Apples</label> <cfinput id="pickers5" name="pickmany" type="checkbox" value="Oranges"> <label for="pickers5">Oranges</label> <cfinput id="pickers6" name="pickmany" type="checkbox" value="Mangoes"> <label for="pickers6">Mangoes</label> <br/> <cfinput name="pickmany-selected" bind="{pickmany}"><br /> </cfform> </body> </html> Most applications call a CFC function, or JavaScript function, or use a URL to make an HTTP request (typically to a CFML page), and pass bind parameters as the function or URL parameters. The following example uses the same form as the first example in the preceding section, but uses a different bind expression with the following features:
The following example shows the bindapp.cfm page: <html> <head> </head> <body> <cfform name="mycfform"> First Name: <cfinput type="text" name="firstname" value=""><br> Last Name: <cfinput type="text" name="lastname" value=""><br> Domain: <cfinput type="text" name="domain" value=""><br> E-mail: <cfinput type="text" name="email" bind="cfc:bindFcns.getEmailId({firstname@keyup},{lastname@keyup}, {domain@keyup})"> </cfform> </body> </html> The following example shows the bindFcns.cfc CFC file: <cfcomponent> <cffunction name="getEmailId" access="remote"> <cfargument name="firstname"> <cfargument name="lastname"> <cfargument name="domain"> <cfreturn "#left(arguments.firstname,1)#.#arguments.lastname#@#lcase(arguments.domain)#"> </cffunction> </cfcomponent> Many of the examples in the documentation for ColdFusion Ajax features use binding, including more complex forms of binding. Using the cfajaxproxy tag to bind to display controlsThe cfajaxproxy tag with a bind attribute makes any of the following elements dependent on one or more bound ColdFusion Ajax controls:
The function or request executes whenever a specific event (by default, the onChange event) of the bound control occurs. Note: if you specify a bind attribute with a URL,
the HTTP request includes a _CF_NODEBUG URL
parameter. ColdFusion checks this value, and when it is true, does
not append to the response any debugging information that it normally
would send. This behavior ensures that JSON responses to Ajax requests
do not include any non-JSON (that is, debugging information) text.
The cfajaxproxy tag includes the following attributes that determine how the proxy handles the data returned by the function or the page:
Binding a function or request by using the cfajaxproxy tag enables you to perform a server-side action, such as updating a database by using bind parameter values based on a user action in some control, and then run a specific action or set of actions in one or more controls based on the server response. Because it uses an onSuccess function to process the return from the server, this form of binding provides substantially more flexibility than a CFML control bind parameter. This format also lets you use a control bind parameter for one kind of action, and the cfajaxproxy tag for a different activity. For example, if you have a form with an editable cfgrid control and a delete button that a user clicks to delete a grid row. The application must have the following behaviors:
Implement these behaviors by doing the following:
The following code snippets show how you could do this: <cfajaxproxybind="cfc:mycfc.deleteRow({deletebutton@click}, {mygrid.id@none}"onSuccess="ColdFusion.Grid.refresh('mygrid', true)"> ... <cfinput type="button" name="deletebutton"> <cfgrid name="mygrid" bind="mycfc.update({cfgridpage}, {cfgridpagesize}, {cfgridsortcolumn}, {cfgridsortdirection})> The following complete example shows a simple use of the bind attribute in a cfajaxproxy tag. For the sake of brevity, the bind expression calls a JavaScript function; as a result, the cfajaxproxy tag cannot use a onError attribute. <html> <head> <script language="javascript"> function test(x,y){ return "Hello, " + x + "!"; } function callbackHandler(result){ alert("Bind expression evaluated. Result: \n" + result); } </script> <cfajaxproxy bind="javascript:test({input1@none},{button1@click})" onSuccess="callbackHandler"> </head> <body> <cfform name="mycfform"> <cfinput type="text" value="" name="input1" size="30"> <cfinput type="button" name="button1" value="Submit"> </cfform> </body> </html> Getting bindable attribute values in JavaScriptUse the ColdFusion.Ajax.submitForm function in your JavaScript code to get the current value of any attribute of a bindable control. This technique is useful for getting values for complex controls such as cfgrid and cftree. For more information, see the ColdFusion.Ajax.submitForm function in the CFML Reference. |