Skip to content

The Form Tag Library

thofrey edited this page Apr 1, 2014 · 7 revisions

Table of Contents

  1. Overview
  2. Enhanced event-bean Command
  3. Configuration and Using the Form Library
  4. Common Questions About the Form Tag Library
  5. A Word About Auto-Generated ID Attribute Values
  6. Standard Attributes, Event Attributes and Custom Attributes Reference
  7. Additional Information and Considerations

Overview

The Mach-II form tag library is an comprehensive set of data binding aware custom CFML tags that produce HTML form elements. Each tag supports all corresponding HTML form element attributes in an familiar and intuitive to use manner. The generated output of each tag is HTML 4.01/XHTML 1.0 compliant. The form tag library was introduced in Mach-II Simplicity (1.8+).

The big difference between other form tag libraries and the Mach-II form tag library is that our library is integrated and designed to work with Mach-II request workflow. This gives our library access to Mach-II related functionality in addition to reducing the effort involved in making an user friendly HTML form. As you will see in the following examples, the form tag library makes developing views with forms easier to develop, maintain and ultimately read when editing code. In the future, this library will integrate with our planned validation framework (which will be independent from the MVC component of Mach-II just like caching and logging) and will provide seamless integration between client and server side validation.

Since illustrated examples are the most convincing, let's look through the library with corresponding HTML output.

Enhanced event-bean Command

We are also developing an enhanced event-bean command with nested inner-bean and field tags. This allows you to populate nested beans (beans of composition) and directly integrates with the form tag library. Check out Event-Beans: Event more fruitier for more information. The event-bean enhancement was developed off a concept submitted by a community member through our call for features program. Just proves that at Mach-II - we're community driven.

Configuration and Using the Form Library

The form library is basically a collection of CFML custom tags. Utilizing it in Mach-II views is as simple as adding an tag library import directive to the top each view that uses the library:

    <cfimport prefix="form" taglib="/MachII/customtags/form" />

We indicated that we will use the "form" prefix in all of our tags. More on this later.

Due to the fact that CFML engines import tag libraries at the time .cfm files are compiled, the Mach-II framework cannot "magically" include the library for you on each page.

The form Tag

This tag renders a HTML <form> tag and sets a bind location so that all nested form library tags can bind to an object or the Mach-II event object automatically dynamically at runtime. It is ok if this does not make complete sense at the moment as you will see data binding in action shortly.

For the sake of having a concrete example, lets build a form that models an User bean. Some attributes of User are firstName, lastName, birthDate, favoriteSeason, favoriteHoliday and favoriteColors. Our User has all the corresponding getters/setters that model those attributes. Let's take a peek at our form if we just ask for first and last names:

    <cfimport prefix="form" taglib="/MachII/customtags/form" />

    <form:form actionEvent="processUser" bind="user">
        <h4>First Name</h4>
        <p><form:input path="firstName" /></p>
        <h4>Last Name</h4>
        <p><form:input path="lastName" /></p>
        <p><input type="submit" value="Save Changes" /></p>
    </form:form>

Notices that our form tag has two attributes. The actionEvent attribute indicates the event name our form will post to and the bind attribute is telling the library that we want to use the User bean that is currently in the Mach-II Event object. Let's pretend that our User bean already has the first name of Bella and the last name of Swan already in the bean. This is the HTML the form library would generate:

    <form method="post" encType="multipart/form-data" action="index.cfm?event=processUser">
        <h4>First Name</h4>
        <p><input id="firstName" value="Bella" type="text" name="firstName"/></p>
        <h4>Last Name</h4>
        <p><input id="lastName" value="Swan" type="text" name="lastName"/></p>
        <p><input type="submit" value="Save Changes" /></p>
    </form>

As you can see, we did not have to do the tedious process having to manually get data from our user bean among other things. This is an error-prone process and hard to maintain. This is what our source code would look like if we had to do everything manually:

    <form method="post" encType="multipart/form-data" action="#BuildUrl('processUser')#">
        <h4>First Name</h4>
        <p><input id="firstName" value="#event.getArg('user').getFirstName()#" type="text" name="firstName"/></p>
        <h4>Last Name</h4>
        <p><input id="lastName" value="#event.getArg('user').getLastName()#" type="text" name="lastName"/></p>
        <p><input type="submit" value="Save Changes" /></p>
    </form>

Available Syntax for Bind Attribute

Currently, the bind attribute of the form tag allows for three different ways to provide a bind for the form.

  • Simple dot path shortcut -- ex. bind="user" is equivalent shortcut to the M2 EL syntax of bind="${event.user}"
  • M2 EL syntax - ex. bind="${event.user}" or bind="${event.user.address}" (added in after the release of Mach-II 1.8 Beta 1)
  • Pass in a bean directly using CFML -- ex. bind="#variables.someBean#" (added in after the release of Mach-II 1.8 Beta 1)

A few notes to be aware of:

  • If you do not specify the bind attribute, the form tag will try to bind to the Mach-II Event object.
  • If you need to bind to multiple beans that are not in a single bean composition hierarchy (i.e. User has an Address), you will need to use the bind tag which allows for multiple bind contexts in a single form. See more information below.

Auto-Focus of First Form Field

By default, the form will auto-focus the user cursor to the first form field in the form. This feature can by programmatically turned off or set to a different field id. If two forms exists on the page, the first form will get the auto-focus unless it is turned off. Best of all, this feature gracefully degrades if javascript is not enabled in the browser.

Setting the auto-focus to focus on a different element

This is easy to accomplish by indicating the id that the form should focus to by using the autoFocus attribute of the form tag. In this example, we are focusing to the last form element (lastName) in the form:

    <cfimport prefix="form" taglib="/MachII/customtags/form" />

    <form:form actionEvent="processUser" bind="user" autoFocus="lastName">
        <h4>First Name</h4>
        <p><form:input path="firstName" /></p>
        <h4>Last Name</h4>
        <p><form:input path="lastName" /></p>
        <p><input type="submit" value="Save Changes" /></p>
    </form:form>

Disabling auto-focus on a form

Sometimes more than one form will exist on the final output to a browser. Most commonly this might be a login form that exists at in the page header. Usually you will not want to auto-focus the user input to this form all the time. To disable auto-focus for a particular form, just use a boolean value (i.e. false or 0) in the autoFocus attribute:

    <cfimport prefix="form" taglib="/MachII/customtags/form" />

    <form:form actionEvent="processUser" bind="user" autoFocus="false">
        <h4>First Name</h4>
        <p><form:input path="firstName" /></p>
        <h4>Last Name</h4>
        <p><form:input path="lastName" /></p>
        <p><input type="submit" value="Save Changes" /></p>
    </form:form>

form Tag Attributes

Name Required Default Description
actionEvent true n/a Name of event to process this form.
actionModule false name of current module Name of module to use with the event to process this form.
actionUrlParams false none Name value pairs in pipe (
autoFocus false defaults to first form element id By default, the form will auto-focus to the first form element. You can provide an id of another element in this attribute to auto-focus to something other than the default. Providing a value of false or 0 disables auto-focus on the form entirely.
encType false multipart/form-data Specifies the encType of the form.
method false post Specifies the type of form post to make (get or post).
bind false Mach-II Event object Specifies the name of the event arg to try to bind to.
p optional n/a Name / value pair list or struct of URL parameters to build the URL with. Use the p namespace (see custom attributes.
q optional n/a Name / value pair list or struct of query string parameters to append to the end of a route (only valid with route). Use the q namespace (see custom attributes
x optional n/a Name / value pair list or struct of additional non-standard attribute to insert into the rendered tag output. Use the p namespace (see custom attributes.

All standard attributes, event attributes (onClick, etc.) and non-standard attributes (x namespace only) are supported. Additional supported event attributes are onsubmit() and onreset(). Please remember that event attribute such as onclick are supported in our implementation (as they are part of the W3C specifications) however they are not much use since a form tag does not get any direct user interaction.

The input Tag

This tag renders an HTML input tag with the type of text. We've seen it in action already in the previous section, however this tag supports all attributes that our HTML counterpart supports.

The path attribute is the magic behind the tag. It transverses a given path that could be a nested set of beans. For example, if our User bean had an Address bean inside of it all you needed to do is this:

    <form:form actionEvent="processUser" bind="user">
        <h4>First Name</h4>
        <p><form:input path="firstName" /></p>
        <h4>Last Name</h4>
        <p><form:input path="lastName" /></p>
        <h4>State</h4>
        <p><form:input path="address.state" /></p>
        <h4>Zip Code</h4>
        <p><form:input path="address.zipCode" /></p>
        <p><input type="submit" value="Save Changes" /></p>
    </form:form>

The path attribute takes a dot path in which it uses to obtain the value. For example, the path of address.state in the above code would equal to event.getArg('user').getAddress().getState(). So using the above source code, the following would generate this HTML output provided that the getters for state and zip code returned WA and 98331 respectively:

    <form method="post" encType="multipart/form-data" action="index.cfm?event=processUser">
        <h4>First Name</h4>
        <p><input id="firstName" value="Bella" type="text" name="firstName"/></p>
        <h4>Last Name</h4>
        <p><input id="lastName" value="Swan" type="text" name="lastName"/></p>
        <h4>State</h4>
        <p><input id="address.state" value="WA" type="text" name="address.state"/></p>
        <h4>Zip Code</h4>
        <p><input id="address.zipCode" value="98331" type="text" name="address.zipCode"/></p>
        <p><input type="submit" value="Save Changes" /></p>
    </form>

As you can see, the name attribute value was generated based off the last value of the dot path. However, there are certain situations where you want the data binding provided by the form library but need to explicitly set the form element name.

    <form:input path="firstName" />
    <form:input path="firstName" name="fName" />

Defining the a path without a name attributes causes the tag to automatically generate a name based off the path. However on the second line, we are still using the data binding, but we are explicitly setting the name of the input to fName. Also, the form library automatically sets the value of the id of the form element to the same value as the name if you do not define an id attribute.

input Tag Attributes

Name Required Default Description
path false (use if no name and value attribute is used) n/a The path in the bound object to get the value
name false (use if no path is defined or custom element name is required) value from path The name of the form element (the value is automatic if not defined and a path attribute is defined).
value false (use if no path is defined or a custom value to override the value provided by path is required) value from path The value to use.
disabled false
readonly false false (takes boolean) Set to true to make the form element read only.
maxlength false attribute is not set if not defined (takes numeric) Sets the maximum input length of the form element.
size false attribute is not set if not defined (takes numeric) Sets the size of the form element.

All standard attributes, event attributes (onClick, etc.) and non-standard attributes (x namespace only) are supported.

The button Tag

This tag renders an HTML input tag with the type of button, reset, submit, or image depending on the type and attributes provided. The button tag supports the path attribute for data binding as do all the form custom tags. Here is a simple example of the button tag being used as a submit button in a form with the name and value attributes being explicitly provided. As with other form tags, if a path attribute is provided, this will set the name, value, and id attributes of the HTML input tag.

    <form:form actionEvent="processUser" bind="user">
        <p><form:button name="submit" value="Save Changes" /></p>
    </form:form>

This produces the following HTML output:

    <form method="post" action="index.cfm?event=processUser">
        <p><input type="submit" name="submit" value="Save Changes" /></p>
    </form>

Note that if a type attribute is not provided in the button tag, the type will default to submit. Types of button and reset are also supported.

An input type of image is also supported, and as in HTML, this will always be a submit button. To render an image as a submit button, simply include the src attribute in the button tag.

    <form:form actionEvent="processUser" bind="user">
        <p><form:button src="/path/to/image.gif" name="submit" value="Save Changes" /></p>
    </form:form>

If you provide a type other than submit in addition to providing the src attribute, an exception will be thrown.

The image input type also supports an alt attribute, and if this is not provided the value attribute is used as the value of alt.

The src attribute and the HtmlHelperProperty

If you are using the HtmlHelperProperty, you can use the same shortcut paths for images with the addition of asset timestamps that the property offers. If you have not defined the HtmlHelperProperty, a full web path to the image for the button must be defined.

button Tag Attributes

Name Required Default Description
path false (use if no name and value attribute is used) n/a The path in the bound object to get the value
name false (use if no path is defined or custom element name is required) value from path The name of the form element (the value is automatic if not defined and a path attribute is defined).
value false (use if no path is defined of custom element value is required) value from path The value of the input tag. This is also used as the alt attribute for image inputs if alt is not provided.
type false submit The type of button. Valid values are button, reset, and submit.
src false n/a The path to an image to use for the button. This results in an HTML input type of image. Image inputs will always acts as submit buttons.
alt false n/a The alt text to associate with an image input.
disabled false false (takes boolean) Set to true to disable the form element.

All standard attributes, event attributes (onClick, etc.) and non-standard attributes (x namespace only) are supported.

The checkbox Tag

This tag renders an HTML input tag with the type of checkbox. Let's continue with the premise outlined above and let the user select their favorite colors.

    <form:form actionEvent="processUser" bind="user">
        <!--- firstName, lastName, etc. --->
        <h4>Your Favorite Colors</h4>
        <p><form:checkbox path="favoriteColors" value="red"/> Red</p>
        <p><form:checkbox path="favoriteColors" value="green"/> Green</p>
        <p><form:checkbox path="favoriteColors" value="blue"/> Blue</p>
        <p><form:checkbox path="favoriteColors" value="yellow"/> Yellow</p>
        <p><form:checkbox path="favoriteColors" value="pink"/> Pink</p>
        <p><input type="submit" value="Save Changes" /></p>
    </form:form>

Which produces HTML output like this:

    <form method="post" encType="multipart/form-data" action="index.cfm?event=processUser">
        <p>
            <input id="favoriteColor_red" value="red" type="checkbox" name="favoriteColors"/>
            <input name="_-_favoriteColors" type="hidden" value="" /> Red
        </p>
        <p>
            <input id="favoriteColor_green" value="green" type="checkbox" name="favoriteColors"/>
            <input name="_-_favoriteColors" type="hidden" value="" /> Green
        </p>
        <p>
            <input id="favoriteColor_blue" value="blue" type="checkbox" name="favoriteColors"/>
            <input name="_-_favoriteColors" type="hidden" value="" /> Blue
        </p>
        <p>
            <input id="favoriteColor_yellow" value="yellow" type="checkbox" name="favoriteColors"/>
            <input name="_-_favoriteColors" type="hidden" value="" /> Yellow
        </p>
        <p>
            <input id="favoriteColor_pink" value="pink" type="checkbox" name="favoriteColors"/>
            <input name="_-_favoriteColors" type="hidden" value="" /> Pink
        </p>
        <p><input type="submit" value="Save Changes" /></p>
    </form>

As you can see, the name of the checkbox elements has been generated of the path and the id (which must be unique) was generated off the name attribute value plus the data in the value attribute. The checkbox form tag will also auto-check an element if the value is in the list of values in the specified path.

The data binding for the checkbox tag is not case sensitive.

checkbox Hidden Fields

You might have noticed that the above are the hidden fields after each checkbox element. This is because HTML has a quirk in it. When a checkbox is not checked, the value is not part of the form post that the web browser sends to the server. We use the hidden field to indicate to Mach-II that checkbox was on the HTML page and that all elements were "unchecked" when we do the data binding on the server side. We use the convention of prefixing the hidden field's name with one underscore, one dash and finally one underscore (_-_) and then fellowed by the full name of the checkbox. This lets Mach-II know that a checkbox was visible in the form and that you want to bind a value to object on the other side (using <event-bean>) and to reflect the state of the checkbox whether or not the web browser posted the checkbox (because it was unchecked).

checkbox Tag Attributes

Name Required Default Description
path false (use if no name and value attribute is used) n/a The path in the bound object to get the value
name false (use if no path is defined or custom element name is required) value from path The name of the form element (the value is automatic if not defined and a path attribute is defined).
value false (use if no path is defined) value from path The value of the checkbox
checked false n/a Explicitly checks the checkbox (boolean)
checkValue false n/a The current value of the target to try to match against the value if data binding is not being use with the path attribute (Uses ListFindNoCase for lists).
disabled false false (takes boolean) Set to true to disable the form element.

All standard attributes, event attributes (onClick, etc.) and non-standard attributes (x namespace only) are supported.

The checkboxGroup Tag

The checkboxGroup tag renders multiple HTML input tags with the type of checkbox and corresponding formatting / display information. Compared with the single checkbox tag above, the checkboxGroup tag allows for simpler syntax in the generation of multiple checkbox inputs.

For example, the checkbox sample code from above:

    <form:form actionEvent="processUser" bind="user">
        <!--- firstName, lastName, etc. --->
        <h4>Your Favorite Colors</h4>
        <p><form:checkbox path="favoriteColors" value="red"/> Red</p>
        <p><form:checkbox path="favoriteColors" value="green"/> Green</p>
        <p><form:checkbox path="favoriteColors" value="blue"/> Blue</p>
        <p><form:checkbox path="favoriteColors" value="yellow"/> Yellow</p>
        <p><form:checkbox path="favoriteColors" value="pink"/> Pink</p>
        <p><input type="submit" value="Save Changes" /></p>
    </form:form>

Would be written as follows using the checkboxGroup tag:

    <form:form actionEvent="processUser" bind="user">
        <!--- firstName, lastName, etc. --->
        <h4>Your Favorite Colors</h4>
        <form:checkboxGroup path="favoriteColors" items="red,green,blue,yellow,pink">
        <p>${output.checkbox} <label for="${output.id}">${output.label}</label></p>
        </form:checkboxGroup>
        <p><input type="submit" value="Save Changes" /></p>
    </form:form>

As you can glean from this example, the checkboxGroup tag loops over a collection and outputs a group of checkbox inputs. Let's look at each attribute of the checkboxGroup tag and how the output works.

The path attribute functions as with all the form tags. Since the form is bound to user, the attribute favoriteColors of user will determine which checkbox inputs are checked. Since no name attribute is provided, favoriteColors will also be the name of each checkbox input. The name and path attribute may both be provided if you want the name of the checkbox inputs to be different than the name of the CFC attribute to which the selected value is bound.

Two separate attributes, items and labels, are used to indicate the value and display label for each checkbox input. The items and labels attributes may be one of the following data types:

  • A list. You may specify the list delimiter by using the delimiter attribute of the checkboxGroup tag (comma is used as a default).
  • A struct. If a struct is provided the struct key is used as the value for the checkbox input, with the struct value being used as the label for the checkbox input. Note that if a struct is provided as the items attribute the labels attribute is redundant and therefore is ignored if provided. You can control the sorting of the struct (since structs are unordered datatypes) via the displayOrder attribute.
  • One-dimensional array with simple values (e.g. strings) as the array elements.
  • One-dimensional array of structs, with struct keys named label (default or configured via labelKey attribute) and value (default or configured via valueKey attribute) in each struct.
  • A query. If a query is provided for items and contains query columns of label and value, those will be used as the label and value for each checkbox input. If the query does not contain columns named label and value, the labelCol and valueCol attributes of the checkboxGroup tag must be provided. As with the struct example outlined above, if a query object is used as the items attribute, the labels attribute is redundant and therefore is ignored if provided.

Note that if both the items and labels attributes are provided they must be of the same data type.

The items attribute is required, and is used to indicate the value used for each member of the checkbox group. Items can of course be dynamic (e.g. items="#myVar#"), and if a labels attribute is not provided the item values are used as the checkbox input labels as well.

The labels attribute, which is omitted in the example above, may be provided when a list or one-dimensional array containing simple values is used as the items attribute. To reiterate what was stated above, if items and labels are both provided, they must be of the same data type. Review the bullet list of data types above for cases in which labels is ignored.

Note the special syntax for outputting the checkbox, label tag, and label text. Rather than the checkboxGroup tag pre-determining the formatting of the output, the use of ${output} style syntax allows you to control the HTML output generated by the checkboxGroup tag. This functions as follows:

  • ${output.checkbox} is the checkbox tag itself, which includes the name and value of the checkbox.
  • ${output.id} is the HTML ID for the checkbox. This is generated automatically by the checkboxGroup tag and follows the format nameOfCheckboxGroup_HTMLSafeVersionOfValue.
  • ${output.label} is the label to display for the checkbox input.

The following data types are supported as either the path value or the checkValue attribute, which indicates the checkboxes in the group to be checked:

  • A list. You may use a delimiter other than a comma (the default) by providing a delimiter attribute to the checkboxGroup tag, but note that only one delimiter attribute is supported so if you are also supplying items or values as a list and using a deilmiter other than a comma, the delimiter must match between the checkValue attribute and other lists being used as tag attributes.
  • A struct. In the struct used for the checkValue attribute, the key is the value to match against the item list, and the value of the struct key should be set to a boolean (true or false) to indicate whether or not the checkbox with the corresponding value of the struct key should be checked. Note that since the default for the value of checked is false, you do not have to provide anything in the struct other than the values you wish to be checked.
  • A one-dimensional array of simple values.
  • A query. You must indicate the column name using the checkValueCol attribute to use to build the list of check values.

checkboxGroup Tag Attributes

Name Required Default Description
path false (use if no name attribute is used) n/a The path in the bound object that determines the checked values in the checkbox group.
name false (use if no path is defined or if a custom element name is required) value from path The name of the form element (the value is automatic if not defined and a path attribute is defined).
items true n/a The values to use as the values and optionally display labels for the checkboxes. The values in items are used as labels if the labels attribute is not provided
labels false (values in items are used as labels if labels is not provided) n/a The labels to use with the checkboxes. If both items and labels are provided they must be the same data type.
checkValue false (use if no path is defined or a custom value to override the value provided by path is required) value from path The values of the checkbox inputs that will have their checked attributes set to true
checkValueCol false n/a If checkValue is a query, use this attribute to indicate the query column name to use to build the check value list.
delimiter false (may be used if items and optionally labels is a list) comma The delimiter used in the list provided as the items (and optionally labels and checkValue) attributes. Note that if items is used with either labels or checkValue (or both), and these are all lists, they must use the same delimiter.
labelCol false label If items is a query, the query column to use as the label for the checkboxes.
valueCol false value If items is a query, the query column to use as the value for the checkboxes.
labelKey false label If items is an array of structs, the key name to use as the label for the checkboxes.
valueKey false value If items is an array of structs, the key name to use as the value for the checkboxes.
disabled false false (takes boolean) Set to true to disable the form element.
displayOrder false Takes a list or array Used to control the display order when a struct is passed to the items attributes. Indicate a list or array or key names in order to display. Use * to indicate all keys minus any other key that is indicated in the list.

The radio Tag

This tag renders an HTML input tag with the type of radio. Continuing with our example, let's show how an user could select his/her favorite season of the year.

    <form:form actionEvent="processUser" bind="user">
        <!--- firstName, lastName, favoriteColors, etc. --->
        <h4>Your Favorite Season of the Year</h4>
        <p><form:radio path="favoriteSeason" value="Winter"/> Winter</p>
        <p><form:radio path="favoriteSeason" value="Spring"/> Spring</p>
        <p><form:radio path="favoriteSeason" value="Summer"/> Summer</p>
        <p><form:radio path="favoriteSeason" value="Autumn"/> Autumn</p>
        <p><input type="submit" value="Save Changes" /></p>
    </form:form>

Which produces HTML output like this:

    <form method="post" encType="multipart/form-data" action="index.cfm?event=processUser">
        <p><input id="favoriteSeason_Winter" value="Winter" type="radio" name="favoriteSeason"/> Winter</p>
        <p><input id="favoriteSeason_Spring" value="Spring" type="radio" name="favoriteSeason"/> Spring</p>
        <p><input id="favoriteSeason_Summer" value="Summer" type="radio" name="favoriteSeason"/> Summer</p>
        <p><input id="favoriteSeason_Autumn" value="Autumn" type="radio" name="favoriteSeason"/> Autumn</p>
        <p><input type="submit" value="Save Changes" /></p>
    </form>

radio Tag Attributes

Name Required Default Description
path false (use if no name and value attribute is used) n/a The path in the bound object to get the value
name false (use if no path is defined or custom element name is required) value from path The name of the form element
value false (use if no path is defined or a custom value to override the value provided by path is required) value from path The value to use.
checked false n/a Explicitly checks the checkbox (boolean)
disabled false false (takes boolean) Set to true to disable the form element.
size false attribute is not set if not defined (takes numeric) Sets the size of the form element.

All standard attributes, event attributes (onClick, etc.) and non-standard attributes (x namespace only) are supported.

The radioGroup Tag

The radioGroup tag renders multiple HTML input tags with the type of radio and corresponding formatting / display information. Compared with the single radio tag above, the radioGroup tag allows for simpler syntax in the generation of multiple radio inputs.

For example, the radio sample code from above in which we use the seasons of the year:

    <form:form actionEvent="processUser" bind="user">
        <!--- firstName, lastName, favoriteColors, etc. --->
        <h4>Your Favorite Season of the Year</h4>
        <p><form:radio path="favoriteSeason" value="Winter"/> Winter</p>
        <p><form:radio path="favoriteSeason" value="Spring"/> Spring</p>
        <p><form:radio path="favoriteSeason" value="Summer"/> Summer</p>
        <p><form:radio path="favoriteSeason" value="Autumn"/> Autumn</p>
        <p><input type="submit" value="Save Changes" /></p>
    </form:form>

Using a list for the data, the example would be written as follows using the radioGroup tag:

    <form:form actionEvent="processUser" bind="user">
        <!--- firstName, lastName, favoriteColors, etc. --->
        <h4>Your Favorite Season of the Year</h4>
        <form:radioGroup path="favoriteSeason" items="Winter,Spring,Summer,Autumn">
            <p>${output.radio} <label for="${output.id}">${output.label}</label></p>
        </form:radioGroup>
        <p><input type="submit" value="Save Changes" /></p>
    </form:form>

As you can glean from this example, the radioGroup tag loops over a collection and outputs a group of radio inputs. Let's look at each attribute of the radioGroup tag and how the output works.

The path attribute functions as with all the form tags. Since the form is bound to user, the attribute favoriteSeason of user will determine which radio input is checked. Since no name attribute is provided, favoriteSeason will also be the name of each radio input. The name and path attribute may both be provided if you want the name of the radio inputs to be different than the name of the CFC attribute to which the selected value is bound.

Formatting Template

Note the special syntax (formatting template) outputting the radio button, label tag, and label text. Rather than the radioGroup tag pre-determining the formatting of the output, the use of ${output} style syntax allows you to control the HTML output generated by the radioGroup tag. This functions as follows:

  • ${output.radio} is the radio input tag itself, which includes the name and value of the radio input.
  • ${output.id} is the HTML ID for the radio input. This is generated automatically by the radioGroup tag and follows the format nameOfRadioGroup_HTMLSafeVersionOfValue.
  • ${output.label} is the label to display for the radio input.

Two separate attributes, items and labels, are used to indicate the value and display label for each radio input. The items and labels attributes may be one of the following data types:

Lists

You may specify the list delimiter by using the delimiter attribute of the radioGroup tag (comma is used as a default).

    <form:form actionEvent="processUser" bind="user">
        <!--- firstName, lastName, favoriteColors, etc. --->
        <h4>Your Favorite Season of the Year</h4>
        <form:radioGroup path="favoriteSeason" items="Winter,Spring,Summer,Autumn">
            <p>${output.radio} <label for="${output.id}">${output.label}</label></p>
        </form:radioGroup>
        <p><input type="submit" value="Save Changes" /></p>
    </form:form>

In this example, both the radio value and the label are the same. If we wanted to change that, we could use the labels attribute which matches by list position with the items attribute:

    <form:form actionEvent="processUser" bind="user">
        <!--- firstName, lastName, favoriteColors, etc. --->
        <h4>Your Favorite Season of the Year</h4>
        <form:radioGroup path="favoriteSeason" items="1,2,3,4" labels="Winter,Spring,Summer,Autumn">
            <p>${output.radio} <label for="${output.id}">${output.label}</label></p>
        </form:radioGroup>
        <p><input type="submit" value="Save Changes" /></p>
    </form:form>

This would produce:

    <form actionEvent="processUser" bind="user">
            <!--- firstName, lastName, favoriteColors, etc. --->
            <h4>Your Favorite Season of the Year</h4>
            <p><form:radio path="favoriteSeason" value="1"/> Winter</p>
            <p><form:radio path="favoriteSeason" value="2"/> Spring</p>
            <p><form:radio path="favoriteSeason" value="3"/> Summer</p>
            <p><form:radio path="favoriteSeason" value="4"/> Autumn</p>
            <p><input type="submit" value="Save Changes" /></p>
    <form>

Structs

If a struct is provided the struct key is used as the value for the radio input, with the struct value being used as the label for the radio input. Note that if a struct is provided as the items attribute the labels attribute is redundant and therefore is ignored if provided. You can control the sorting of the struct (since structs are unordered datatypes) via the displayOrder attribute.

    <cfset variables.seasons = StructNew() />
    <cfset variables.seasons["1"] = "Winter" />
    <cfset variables.seasons["2"] = "Spring" />
    <cfset variables.seasons["3"] = "Summer" />
    <cfset variables.seasons["4"] = "Fall" />

    <form:form actionEvent="processUser" bind="user">
        <!--- firstName, lastName, favoriteColors, etc. --->
        <h4>Your Favorite Season of the Year</h4>
        <form:radioGroup path="favoriteSeason" items="#variables.seasons#">
            <p>${output.radio} <label for="${output.id}">${output.label}</label></p>
        </form:radioGroup>
        <p><input type="submit" value="Save Changes" /></p>
    </form:form>

This would put the following using the keys (alpha-numeric ASC are the sort order):

    <form:form actionEvent="processUser" bind="user">
            <!--- firstName, lastName, favoriteColors, etc. --->
            <h4>Your Favorite Season of the Year</h4>
            <p><form:radio path="favoriteSeason" value="1"/> Winter</p>
            <p><form:radio path="favoriteSeason" value="2"/> Spring</p>
            <p><form:radio path="favoriteSeason" value="3"/> Summer</p>
            <p><form:radio path="favoriteSeason" value="4"/> Autumn</p>
            <p><input type="submit" value="Save Changes" /></p>
    </form:form>

If we wanted to sort the struct by seasons in reverse, we could defined a sort order using displayOrder="4,3,2,1". This attributes takes a list or array of struct key names. See the tag attribute table for more information on using this attribute.

One-Dimensional Array of Simple Values

One-dimensional arrays with simple values (e.g. strings) as the array elements. This will use the array element value for both the radio button value and label.

    <cfset variables.seasons = ArrayNew(1) />
    <cfset ArrayAppend(variables.seasons, "Winter") />
    <cfset ArrayAppend(variables.seasons, "Spring") />
    <cfset ArrayAppend(variables.seasons, "Summer") />
    <cfset ArrayAppend(variables.seasons, "Fall") />

    <form:form actionEvent="processUser" bind="user">
        <!--- firstName, lastName, favoriteColors, etc. --->
        <h4>Your Favorite Season of the Year</h4>
        <form:radioGroup path="favoriteSeason" items="#variables.seasons#">
            <p>${output.radio} <label for="${output.id}">${output.label}</label></p>
        </form:radioGroup>
        <p><input type="submit" value="Save Changes" /></p>
    </form:form>

One-Dimensional Array of Structs

The one-dimensional array of structs allows you control the order with each struct having the keys named label (default or configurable via labelKey attribute) and value (default or configurable via the valueKey attribute) in each struct.

    <cfset variables.seasons = ArrayNew(1) />
    <cfset ArrayAppend(variables.seasons, [value:1, label:'Winter']) />
    <cfset ArrayAppend(variables.seasons, [value:2, label:'Spring']) />
    <cfset ArrayAppend(variables.seasons, [value:3, label:'Summer']) />
    <cfset ArrayAppend(variables.seasons, [value:4, label:'Fall']) />

    <form:form actionEvent="processUser" bind="user">
        <!--- firstName, lastName, favoriteColors, etc. --->
        <h4>Your Favorite Season of the Year</h4>
        <form:radioGroup path="favoriteSeason" items="#variables.seasons#">
            <p>${output.radio} <label for="${output.id}">${output.label}</label></p>
        </form:radioGroup>
        <p><input type="submit" value="Save Changes" /></p>
    </form:form>

Queries

If a query is provided for items and contains query columns of label and value, those will be used as the label and value for each radio input. If the query does not contain columns named label and value, the labelCol and valueCol attributes of the radioGroup tag must be provided. As with the struct example outlined above, if a query object is used as the items attribute, the labels attribute is redundant and therefore is ignored if provided.

    <!--- This query has columns 'id' and 'name' where the the 'name' is the name
        of the season and the 'id' is the unique database row id. --->
    <cfset variables.seasons = "QUERY HERE" />

    <form:form actionEvent="processUser" bind="user">
        <!--- firstName, lastName, favoriteColors, etc. --->
        <h4>Your Favorite Season of the Year</h4>
        <form:radioGroup path="favoriteSeason" items="#variables.seasons#" valueCol="id" labelCol="name">
            <p>${output.radio} <label for="${output.id}">${output.label}</label></p>
        </form:radioGroup>
        <p><input type="submit" value="Save Changes" /></p>
    </form:form>

Special Notes

Note that if both the items and labels attributes are provided they must be of the same data type.

The items attribute is required, and is used to indicate the value used for each member of the radio group. Items can of course be dynamic (e.g. items="#myVar#"), and if a labels attribute is not provided the item values are used as the radio input labels as well.

The labels attribute, which is omitted in the example above, may be provided when a list or one-dimensional array containing simple values is used as the items attribute. To reiterate what was stated above, if items and labels are both provided, they must be of the same data type. Review the bullet list of data types above for cases in which labels is ignored.

radioGroup Tag Attributes

Name Required Default Description
path false (use if no name attribute is used) n/a The path in the bound object that determines the checked value in the radio group.
name false (use if no path is defined or if a custom element name is required) value from path The name of the form element (the value is automatic if not defined and a path attribute is defined).
items true n/a The values to use as the values and optionally display labels for the radio inputs. The values in items are used as labels if the labels attribute is not provided
labels false (values in items are used as labels if labels is not provided) n/a The labels to use with the radio inputs. If both items and labels are provided they must be the same data type.
checkValue false (use if no path is defined or a custom value to override the value provided by path is required) value from path The value of the radio input that will have its checked attribute set to true
delimiter false (may be used if items and optionally labels is a list) comma The delimiter used in the list provided as the items (and optionally labels) attributes. Note that if both items and labels are lists they must use the same delimiter.
labelCol false label If items is a query, the query column to use as the label for the radio inputs.
valueCol false value If items is a query, the query column to use as the value for the radio inputs.
labelKey false label If items is an array of structs, the key name to use as the label for the radio inputs.
valueKey false value If items is an array of structs, the key name to use as the value for the raido inputs.
disabled false false (takes boolean) Set to true to disable the form element.
displayOrder false Takes a list or array Used to control the display order when a struct is passed to the items attributes. Indicate a list or array or key names in order to display. Use * to indicate all keys minus any other key that is indicated in the list.

The password Tag

This tag renders an HTML input tag with the type of password. By the default, the value is not used to pre-populate the form. If you need to pre-populate the value, use the showPassword attribute set to true.

    <form:password path="password" />

password Tag Attributes

Name Required Default Description
path false (use if no name and value attribute is used) n/a The path in the bound object to get the value
name false (use if no path is defined or custom element name is required) value from path The name of the form element (the value is automatic if not defined and a path attribute is defined).
value false (use if no path is defined or a custom value to override the value provided by path is required) value from path The value to use.
disabled false false (takes boolean) Set to true to disable the form element.
readonly false false (takes boolean) Set to true to make the form element read only.
maxlength false attribute is not set if not defined (takes numeric) Sets the maximum input length of the form element.
size false attribute is not set if not defined (takes numeric) Sets the size of the form element.
showPassword false false By default, the password value is not shown. If you want to pre-populate the password value, set the showPassword to true.

All standard attributes, event attributes (onClick, etc.) and non-standard attributes (x namespace only) are supported.

The file Tag

This tag renders an HTML input tag with the type of file. Due to security restrictions with file inputs the value attribute cannot be used to set the value of the input. Path binding may be used, however, and will populate the name and id attributes.

    <form:file path="filename" />

When the file tag is used in a form, the enctype of the form is automatically set to multipart/form-data (1.9+).

file Tag Attributes

Name Required Default Description
path false (use if no name and value attribute is used) n/a The path in the bound object that will be used as the input's name and id attributes
name false (use if no path is defined or custom element name is required) value from path The name of the form element (the value is automatic if not defined and a path attribute is defined).
disabled false false (takes boolean) Set to true to disable the form element.
readonly false false (takes boolean) Set to true to make the form element read only.
maxlength false attribute is not set if not defined (takes numeric) Sets the maximum input length of the form element.
size false attribute is not set if not defined (takes numeric) Sets the size of the form element.

All standard attributes, event attributes (onClick, etc.) and non-standard attributes (x namespace only) are supported.

uploadFile() Function

In order to more easily facilitate file uploads, in addition to the file form tag, a new fileUpload() function has been added to Mach-II. This function is available in any CFC that extends a Mach-II component. The uploadFile() function takes all the attributes of the CFFILE tag, and actually is a convenient wrapper around CFFILE that allows for better integration of file uploads into Mach-II.

The syntax is as follows:

    uploadFile("form field", "destination directory", "name conflict action", "accept", "mode", "attributes")

Only the form field and destination directory are required. All optional attributes default to the same values as the CFFILE tag itself.

The uploadFile() function returns a struct containing the results of the CFFILE tag's execution. This is the exact same struct that is set to the result attribute when using CFFILE directly.

Let's look at an example of using both the file tag and the uploadFile() function. You might have a form as follows:

    <form:form actionEvent="uploadFile">
        <form:file name="theFile" /><br />
        <form:button value="Upload" />
    </form:form>

Assuming the uploadFile event notifies a listener and calls the method processFileUpload, the listener method might look like this:

    <cffunction name="processFileUpload" access="public" output="false" returntype="void">
        <cfargument name="event" type="MachII.framework.Event" required="true" />

        <cfset var uploadResults = uploadFile("theFile", ExpandPath("/"), "overwrite", "application/msword") />
    </cffunction>

This would upload the file contained in the form field theFile (note that you do not call arguments.event.getArg("theFile") but refer to the form field name directly) and return the struct that is generated by the CFFILE tag. In this case the name conflict action is set to overwrite, and the accept attribute has been set to only accept Microsoft Word files as the uploaded file.

As of Mach-II Integrity (1.9.0), the accept attribute accepts a list of mixed file extensions (which must start with a dot) and/or MIME types:

    <cfset var uploadResults = uploadFile("theFile", ExpandPath("/"),
        "overwrite", ".jpg,.gif,.pdf,application/msword") />

Keep in mind that the uploadFile function simply provides a convenience wrapper to the CFFILE tag and does not provide any additional security enhancements to the CFFILE tag. It is still the responsibility of the individual developer to protect their systems from script attacks via CFFILE as described in  articles such as this, and to handle the deletion and removal of invalid or unacceptable files once they are uploaded to the server via the uploadFile function.

The select Tag

This tag renders an HTML select tag. This tag supports rendering option tags by passing data in via an items attribute. You can also nesting option or options tags within the select tag. The details of these additional tags are discussed further down in this documentation document.

Let's continue with our example, let's say we have a struct of holidays where the key name will be used as the option value and key value will be used as the option label.

    <cfset variables.seasons = {
        easter="Easter",
        valentines="Valentine's Day",
        independenceDay="Fourth of July"
        } />
    <form:select path="favoriteHoliday" items="#variables.seasons#">
        <form:option value="-" label="Choose a holiday" />
    </form:select>

This produces the following output:

    <select id="favoriteHoliday" name="favoriteHoliday">
        <option id="favoriteHoliday_-" value="-">Choose a holiday</option>
        <option id="favoriteHoliday_easter" value="easter">Easter</option>
        <option id="favoriteHoliday_independenceday" value="independenceday">Fourth of July</option>
        <option id="favoriteHoliday_valentines" value="valentines">Valentine's Day</option>
    </select>

As you can see, we passed the select tag a struct of options. Using a struct can cause the order of the options in a random order so they will be sorted alphanumerically.

You can also pass it an array or list. If you use an array or list, the each array/list element will be used for the option value and label. The options will be generated in the order they are defined in the array or list. See the options tag for more ideas on what you can do with the items attribute. The item attribute is a shortcut for a nested options tag so see the options tag for complete documentation on attributes and configuration options/examples.

We recommend that if you use a "please select an option" value in the drop down that you use - (dash) as a value by default.

The following data types are supported as either the path value or the checkValue attribute, which indicates the option(s) in the group to be selected:

  • A list. You may use a delimiter other than a comma (the default) by providing a delimiter attribute to the select tag, but note that only one delimiter attribute is supported so if you are also supplying items or values as a list and using a deilmiter other than a comma, the delimiter must match between the checkValue attribute and other lists being used as tag attributes.
  • A struct. In the struct used for the checkValue attribute, the key is the value to match against the item list, and the value of the struct key should be set to a boolean (true or false) to indicate whether or not the checkbox with the corresponding value of the struct key should be checked. Note that since the default for the value of checked is false, you do not have to provide anything in the struct other than the values you wish to be checked. You can control the sorting of the struct (since structs are unordered datatypes) via the displayOrder attribute.
  • A one-dimensional array of simple values.
  • A query. You must indicate the column name using the checkValueCol attribute to use to build the list of check values.

select Tag Attributes

Name Required Default Description
path false (use if no name and value attribute is used) n/a The path in the bound object to get the value
name false (use if no path is defined or custom element name is required) value from path The name of the form element (the checkValue is automatic if path attribute is defined).
checkValue false (use when name is defined zero-length string The value to check each option against for auto-binding. Only use with name attribute and not valid with path attribute.
checkValueCol false
multiple false false (takes boolean) Set to true to allow multiple selections.
readonly false false (takes boolean) Set to true to make the form element read only.
size false attribute is not set if not defined (takes numeric) Sets the size of the form element.
items false n/a Takes a struct, array or list of options to generate (if struct, they will be sorted alphanumerically).
labelCol false label The name of the query column to use when using a query datatype for the options items. Defaults to label as the query column unless specified.
valueCol false value The name of the query column to use when using a query datatype for the options items. Defaults to value as the query column unless specified.
labelKey false label If items is an array of structs, the key name to use as the label for the options items.
valueKey false value If items is an array of structs, the key name to use as the value for the options items.
delimiter false , (comma) The delimiter to use if using a list in the items attribute.
displayOrder false Takes a list or array Used to control the display order when a struct is passed to the items attributes. Indicate a list or array or key names in order to display. Use * to indicate all keys minus any other key that is indicated in the list.
optgroup true n/a The label to apply for the optgroup around a group of options when using the items attributes.

All standard attributes, event attributes (onClick, etc.) and non-standard attributes (x namespace only) are supported.

The option Tag

This tag renders an HTML option tag. Continuing with our example using favorite holidy, we could define each holiday separately.

    <form:select path="favoriteHoliday">
        <form:option value="-" label="Choose a holiday" />
        <form:option value="easter" label="Easter" />
        <form:option value="independenceday" label="Fourth of July" />
        <form:option value="valentines" label="Valentines's Day" />
    </form:select>

This produces the following output:

    <select id="favoriteHoliday" name="favoriteHoliday">
        <option id="favoriteHoliday_-" value="-">Choose a holiday</option>
        <option id="favoriteHoliday_easter" value="easter">Easter</option>
        <option id="favoriteHoliday_independenceday" value="independenceday">Fourth of July</option>
        <option id="favoriteHoliday_valentines" value="valentines">Valentine's Day</option>
    </select>

The label attribute is optional so you could just define a value for each select. By default if no labelis defined, the data provided in thevalue` attribute is used as the option label.

Since the data in the value attribute is used in the auto-generated id attribute, any spaces in that data will be removed when making the id. So if the value was fourth of July the id would be favoriteHoliday_fourthofJuly.

option Tag Attributes

Name Required Default Description
value true n/a Provides the value of the option.
label false uses the data provided in the value attribute Sets the label to be show for the value.
disabled false false (takes boolean) Set to true to disable the form element.
selected false n/a Explicitly selects the option (boolean) otherwise the data binding will select the correct option for this select.

All standard attributes, event attributes (onClick, etc.) and non-standard attributes (x namespace only) are supported.

The options Tag

This tag renders multiple HTML option tags and takes lists, arrays, queries and structs. This tag must be nested inside select tag in order to work.

Building options with Structs

Let's continue with our example, let's say we have a struct of holidays where the key name will be used as the option value and key value will be used as the option label. Looping over structs does not always produce the same output order. By default, the options tag performs a StructSort text ascending before looping over the struct. You can control the sorting of the struct (since structs are unordered datatypes) via the displayOrder attribute.

    <cfset variables.holidays = {
        easter="Easter",
        valentines="Valentine's Day",
        independenceDay="Fourth of July"
        } />

    <form:select path="favoriteHoliday">
        <form:option value="-" label="Choose a holiday" />
        <form:options items="#variables.holidays#" />
    </form:select>

This produces the following output:

    <select id="favoriteHoliday" name="favoriteHoliday">
        <option id="favoriteHoliday_-" value="-">Choose a holiday</option>
        <option id="favoriteHoliday_easter" value="easter">Easter</option>
        <option id="favoriteHoliday_independenceday" value="independenceday">Fourth of July</option>
        <option id="favoriteHoliday_valentines" value="valentines">Valentine's Day</option>
    </select>

Let's say we wanted Valentine's Day be the first holiday displayed, we could make use of the displayOrder attribute. displayOrder expects a list of key names and/or an *. The * is used to indicate all keys except the any other key names in the list. For example, to get Valentine's Day to be displayed first we would do this:

    <cfset variables.holidays = {
        easter="Easter",
        valentines="Valentine's Day",
        independenceDay="Fourth of July"
        } />

    <form:select path="favoriteHoliday">
        <form:option value="-" label="Choose a holiday" />
        <form:options items="#variables.holidays#" displayOrder="valentines,*" />
    </form:select>

This produces the following output:

    <select id="favoriteHoliday" name="favoriteHoliday">
        <option id="favoriteHoliday_-" value="-">Choose a holiday</option>
        <option id="favoriteHoliday_valentines" value="valentines">Valentine's Day</option>
        <option id="favoriteHoliday_easter" value="easter">Easter</option>
        <option id="favoriteHoliday_independenceday" value="independenceday">Fourth of July</option>
    </select>

For example, to get Easter to be displayed last we would do this:

    <cfset variables.holidays = {
        easter="Easter",
        valentines="Valentine's Day",
        independenceDay="Fourth of July"
        } />

    <form:select path="favoriteHoliday">
        <form:option value="-" label="Choose a holiday" />
        <form:options items="#variables.holidays#" displayOrder="*,easter" />
    </form:select>

This produces the following output:

    <select id="favoriteHoliday" name="favoriteHoliday">
        <option id="favoriteHoliday_-" value="-">Choose a holiday</option>
        <option id="favoriteHoliday_valentines" value="valentines">Valentine's Day</option>
        <option id="favoriteHoliday_easter" value="easter">Easter</option>
        <option id="favoriteHoliday_independenceday" value="independenceday">Fourth of July</option>
    </select>

Building options with Lists

Using lists is easy for options as well.

    <form:select path="favoriteHoliday">
        <form:option value="-" label="Choose a holiday" />
        <form:options items="Easter,Valentines's Day,Independence Day" />
    </form:select>

This produces this following output:

    <select id="favoriteHoliday" name="favoriteHoliday">
        <option id="favoriteHoliday_-" value="-">Choose a holiday</option>
        <option id="favoriteHoliday_Easter" value="easter">Easter</option>
        <option id="favoriteHoliday_Valentines_" value="valentines">Valentine's Day</option>
        <option id="favoriteHoliday_Independenceday" value="independenceday">Independence Day</option>
    </select>

Building options with Arrays

Using arrays is simple too! This example shows an array of simple values.

    <cfset variables.holidays = ["Easter","Valentine's Day", "Independence Day" ] />

    <form:select path="favoriteHoliday">
        <form:option value="-" label="Choose a holiday" />
        <form:options items="#variables.holidays#" />
    </form:select>

This produces this following output:

    <select id="favoriteHoliday" name="favoriteHoliday">
        <option id="favoriteHoliday_-" value="-">Choose a holiday</option>
        <option id="favoriteHoliday_Easter" value="easter">Easter</option>
        <option id="favoriteHoliday_Valentines_Day" value="valentines">Valentine's Day</option>
        <option id="favoriteHoliday_Independenceday" value="independenceday">Independence Day</option>
    </select>

We also support an array of structs. By default the label key name is label or it can be configured via the labelKey attribute. By default the value key name for the struct is value or it can be configured via the valueKey attribute.

    <cfset variables.holidays = ArrayNew(1) />
    <cfset temp = StructNew() />
    <cfset temp.label = "Easter Sunday" />
    <cfset temp.value = "Easter" />
    <cfset ArrayAppend(variables.holidays, temp) />
    <cfset temp = StructNew() />
    <cfset temp.label = "Valentine's Day" />
    <cfset temp.value = "Valentines" />
    <cfset ArrayAppend(variables.holidays, temp) />
    <cfset temp = StructNew() />
    <cfset temp.label = "Independence Day" />
    <cfset temp.value = "July4th" />
    <cfset ArrayAppend(variables.holidays, temp) />

    <form:select path="favoriteHoliday">
        <form:option value="-" label="Choose a holiday" />
        <form:options items="#variables.holidays#" />
    </form:select>

This produces this following output:

    <select id="favoriteHoliday" name="favoriteHoliday">
        <option id="favoriteHoliday_-" value="-">Choose a holiday</option>
        <option id="favoriteHoliday_Easter" value="easter">Easter</option>
        <option id="favoriteHoliday_Valentines" value="valentines">Valentine's Day</option>
        <option id="favoriteHoliday_July4th" value="independenceday">Independence Day</option>
    </select>

Building options with Queries

Got a query? It's easy as pie! Pretend that variables.holidays has two columns called id and season_name. As you can see, we are indicating the column names we need for the option value and the label by using the valueCol and labelcol respectively.

    <form:select path="favoriteHoliday">
        <form:option value="-" label="Choose a holiday" />
        <form:options items="#variables.holidays#" labelCol="id" valueCol="id" />
    </form:select>

This produces this following output:

    <select id="favoriteHoliday" name="favoriteHoliday">
        <option id="favoriteHoliday_-" value="-">Choose a holiday</option>
        <option id="favoriteHoliday_Easter" value="easter">Easter</option>
        <option id="favoriteHoliday_Valentines_" value="valentines">Valentine's Day</option>
        <option id="favoriteHoliday_Independenceday" value="independenceday">Independence Day</option>
    </select>

options Tag Attributes

Name Required Default Description
items true n/a Takes a struct, array, query or list of options to generate (if struct, they will be sorted alphanumerically).
delimiter false , (comma) The delimiter to use if using a list in the items attribute and not using the default , list delimiter.
labelCol false label The name of the query column to use when using a query datatype for the options items. Defaults to label as the query column unless specified.
valueCol false value The name of the query column to use when using a query datatype for the options items. Defaults to value as the query column unless specified.
labelKey false label If items is an array of structs, the key name to use as the label for the options items.
valueKey false value If items is an array of structs, the key name to use as the value for the options items.
displayOrder false Takes a list or array Used to control the display order when a struct is passed to the items attributes. Indicate a list or array or key names in order to display. Use * to indicate all keys minus any other key that is indicated in the list.
optgroup true n/a The label to apply for the optgroup around this group of options.

The optgroup Tag

This tag renders an HTML optgroup tag and is used to group together related options in a select list. This tag is used in conjunction of the select and option / options tags. Each user agent (browser) renders opt groups different

    <cfset variables.germanCars = StructNew() />
    <cfset variables.germanCars.bmw = "BMW" />
    <cfset variables.germanCars.vw = "Volkswagon" />
    <cfset variables.germanCars.audi = "Audi" />

    <cfset variables.americanCars = StructNew() />
    <cfset variables.americanCars.ford = "Ford" />
    <cfset variables.americanCars.gm = "General Motors" />

    <form:select path="favoriteCars">
        <form:optgroup label="German Companies">
            <form:options items="#variables.germanCars#"/>
        </form:optgroup>
        <form:optgroup label="American Companies">
            <form:options items="#variables.AmericanCars#"/>
        </form:optgroup>
    </form:select>

You could use the optgroup attribute of either the select tag or options tag as well. This example would produce the same output as the example above:

    <form:select path="favoriteCars">
        <form:options items="#variables.germanCars#" optgroup="German Cars"/>
        <form:options items="#variables.AmericanCars#" optgroup="American Cars"/>
    </form:select>

Both of the examples above produces this same output:

    <select id="favoriteCars" name="favoriteCars">
        <optgroup label="German Companies">
            <option id="favoriteCars_audi" value="audi">Audi</option>
            <option id="favoriteCars_bmw" value="bmw">BMW</option>
            <option id="favoriteCars_vw" value="vw">Volkswagon</option>
        </optgroup>
        <optgroup label="American Companies">
            <option id="favoriteCars_ford" value="ford">Ford</option>
            <option id="favoriteCars_gm" value="gm">General Motors</option>
        </optgroup>
    </select>

options Tag Attributes

Name Required Default Description
label true n/a The label to apply for the optgroup.

The textarea Tag

This tag renders an HTML textarea.

    <form:textarea path="notes" rows="3" cols="20" />

textarea Tag Attributes

Name Required Default Description
path false (use if no name and value attribute is used) n/a The path in the bound object to get the value
name false (use if no path is defined or custom element name is required) value from path The name of the form element (the value is automatic if not defined and a path attribute is defined).
value false (use if no path is defined or a custom value to override the value provided by path is required) value from path The value to use.
rows false n/a Sets the rows value of the textarea.
cols false n/a Sets the cols value of the textarea.

All standard attributes, event attributes (onClick, etc.) and non-standard attributes (x namespace only) are supported.

The hidden tag

This tag renders a HTML input tag with the type of hidden.

    <form:hidden path="orderId" />

This produces:

    <input type="hidden" name="orderId" id="orderId" value="5679981" />

hidden Tag Attributes

Name Required Default Description
path false (use if no name and value attribute is used) n/a The path in the bound object to get the value
name false (use if no path is defined or custom element name is required) value from path The name of the form element (the value is automatic if not defined and a path attribute is defined).
value false (use if no path is defined or a custom value to override the value provided by path is required) value from path The value to use.

All standard attributes, event attributes (onClick, etc.) and non-standard attributes (x namespace only) are supported.

The bind Tag

This tag was added in after the release of Mach-II 1.8 Beta 1. Please the BER or a newer Beta / RC / Stable if available.

This tag does not generate any HTML output, but is an important tag for the form tag library as is enables multiple bind contexts in a single form. Sometimes your form is not modeled around a single bean, so you choose not to bind to a bean in the form tag because there are multiple non-hierarchical bind points (i.e. one bean is not inside another bean via composition). Some code is worth a thousand more words describing this:

    <form:form actionEvent="processSomethingCool">
        <form:bind target="user">
            <!--- form tags for user fields --->
        </form:bind>

        <form:bind target="company">
            <!--- form tags for company fields --->
        </form:bind>
    </from:form>

As you can see, we are switching the bind context in the middle of form. Also, the bind tag switches the bind context back the original context if it is available. Take this sample for instance:

    <form:form actionEvent="processSomethingCool" bind="user">
        <!--- form tags for user fields --->

        <form:bind target="company">
            <!--- form tags for company fields --->
        </form:bind>

        <!--- Additional form tags for user fields --->
    </from:form>

What is going here if we step through the above code:

  • The form tag sets the bind context to the User bean and some user related form fields are processed.
  • The bind tag sets the bind context to the Company bean and saves the previous bind context for later which in this case is the User bean. Some company related form fields are processed.
  • At the end of the bind tag, the original bind context (i.e. User bean) is set as the new bind context.
  • Additional user related form fields are processed.

Available Syntax for Target Attribute for the bind Tag

Currently, the bind attribute of the form tag allows for three different ways to provide a bind for the form.

  • Simple dot path shortcut -- ex. target="user" is equivalent shortcut to the M2 EL syntax of target="${event.user}"
  • M2 EL syntax - ex. target="${event.user}" or target="${event.user.address}"
  • Pass in a bean directly using CFML -- ex. target="#variables.someBean#"
  • If you do not specify the target attribute, the bind tag will bind to the Mach-II Event object directly.

bind Tag Attributes

Name Required Default Description
target false Mach-II Event object Provides a bind path as a M2 EL expression or simple dot path shortcut syntax or passes in a bean via CFML. See above for available options.

Common Questions About the Form Tag Library

How do you used inline styles (i.e. class="someStyle") so that we could style one specific form control in a specific way if needed?

All tags current already support all standard attributes (id, class, style, dir and lang) and all tags except for form, radiogroup, checkboxgroup, option and the options tag support standard event attributes (such as tabIndex, accessKey, onFocus, etc). All tags support all attributes as defined by the W3C.

How would you utilize this when reusing the same form for create account and update account? when creating an account, there is no account variable in the event, so I get the error:

    "A bind named 'account' is not available the current event object."

Actually this question does not have anything to do with the form tag library specifically. Really what this gets at is how best to handle adds and edits with the same form. Let's say I have an event called showPersonForm. In my event handler, I call the getPerson method on my PersonListener. If there's a personID in my event, then I'll get a populated Person object, otherwise I'll get an empty one. Then regardless of what is occurring -- an add or an update, you can then use the binding because there's a bean there.

Ok, if a Person 'has an' Address and some of the form fields includes Address properties (i.e. person.address.streetAddress1) should my empty Person instantiate the associated empty Address object as well?

By default if your Person bean 'has an' Address, then the default value for the address attribute in a Person should be an empty Address bean. It is quite common for beans to use composition (i.e. beans within beans).

How do you define non-W3C attributes in a tag?

While not part of the standard, sometimes it is necessary to add an attribute to tag for Javascript (i.e. the Lightwindow library for Prototype uses the class attribute for configuration parameters) or for browser specific attributes (i.e autocomplete="off" to indicate turning off auto-complete for forms -- which is partially supported by browsers). This can easily be done by using the x namespace support. See the section on specifying attributes using a namespace for more information. However it's simple as prefixing the attributes with the x: namespace:

    <form:form id="assessmentForm" actionEvent="router" x:autocomplete="off">

A Word About Auto-Generated ID Attribute Values

Unless you provide an id attribute, most all form library custom tags (except for form and hidden) will assign a id to each form element and auto-generate a value based off the name value (and value if radio or option form elements). Since the id value cannot contain certain characters (punctuation characters), the framework will change all spaces to _ (dash) and remove all punctuation (using the RegEx expression). We do clean up control characters such as line feeds or tabs.

Examples:

"Dirty" Id Cleaned Id
Valentine's Day Valentines_Day
C.J. Cregg's Birthday CJ_Creggs_Birthday
C. Farrell & Sons C_Farrell__Sons

Mach-II 1.8 using the following UDF to create cleaned versions for id:

    <cffunction name="createCleanId" access="public" returntype="string" output="false"
        hint="
            Creates a cleaned version to be used as an 'id'.
            Changes spaces to '_' and removes most punctuation (that conforms to RegEx '[[:punct:]]')." >
        <cfargument name="dirtyId" type="string" required="true"  />

        <cfset var cleanedId = arguments.dirtyId />

        <cfset cleanedId = REReplaceNoCase(cleanedId, "[[:punct:]]", "", "all") />
        <cfset cleanedId = ReplaceNoCase(cleanedId, " ", "_", "all") />

        <cfreturn cleanedId />
    </cffunction>

Standard Attributes, Event Attributes and Custom Attributes Reference

We support all tag attributes as defined by the specifications set forth by the W3C. All tags support the list in the standard attributes. Most tags (other than form and option) support event attributes. All tags will indicate if they support the event attributes. Non-standard HTML attributes are supported using the x namespace. URL parameters are supported with the p namespace (form tag only) and query string parameters for URL Routes are supported with the q namespace (form tag tag only).

Standard Attributes

All standard attributes are optional and not required.

Attribute Name Description
id The value of id is computed off of the name of the element (combined with value for checkbox and radio - favoriteSeason_winter) if not defined.
class
style
dir
lang
title
accesskey
tabindex

Custom Attributes

Custom attributes are tag attributes that are non-standard HTML attributes for the specific tag. For example you may need to set a tag that is web browser specific, but is not part of the normal W3C approved attributes for the tag.

Specifying Attributes Using Attribute Namespaces

Custom Url Parameters

As we stated above, some Mach-II developers would prefer to specify URL parameters when building URLs by defining name / value pairs instead of passing in a list or struct to the actionParameter attribute. Now, you're problems are solved using attribute namespaces. Using attribute namespaces leaves the door open for future enhancements to the tag and provides an easy a way around having namespace conflicts (i.e. two keys with the same name, but indicate two separate data fragments).

For example (using the same example from above), if we want to use name / value pairs to indicate the userId we would namespace the userId key like so:

    <form:form actionEvent="processUser" bind="user" p:userId="#event.getArg('userId')">

This would ouput code in this fashion (note that the URL string may vary depending on you eventParameter and SES settings):

    <form method="post" encType="multipart/form-data" action="index.cfm?event=processUser&userId=46573">

We strip off the namespace prefix (p:) from the attribute key name and use that as the URL parameter key name when building the URL. The same process applies to the other namespaces we support in the form tag such as the x and q namespaces. Any name / value pairs specified as namespaced attributes will overwrite any key conflicts from the p, q or x attributes.

Non Standard tag attributes

Sometimes a developer needs to use a non-standard attribute within an HTML tag. This may be either for defining some javascript functionality, or utilizing an attribute that is just not yet W3C compliant. In this case the developer should make use of the x namespace. A common example of this would be for stopping auto-complete in input fields. While not W3C compliant some browsers support the attribute autocomplete. This being a non-standard attribute would have to be prefixed by the x namespace as indicated below.

    <form:input path="firstName" x:autocomplete="false" />

this would output the following html code:

    <input type="text" name="firstName" id="firstName" value="John" autocomplete="false" />

Available Namespaces

Namespace Description
p Used to prefix name / value pairs used for the URL parameters when building URLs (form tag only).
q Used to prefix name / value pairs used for query string parameters when building routes (valid only when using the route attribute) (form tag only).
x Uses to prefix name / value pairs for non-standard HTML attributes to be inserted into final output of the form tag. For example, you might use a javascript framework look for a non-standard attribute of a tag in order to perform some functionality on it.

Event Attributes

Attribute Name
tabIndex
accessKey
onFocus
onBlur
onSelect
onChange
onDblClick
onMouseDown
onMouseUp
onMouseOver
onMouseMove
onMouseOut
onKeyPress
onKeyDown
onKeyUp

Additional Information and Considerations

The M2SFP for this feature were filed under multiple tickets (numbers from former trac-wiki)

  • #211 "task: Implement Form Tag Library (closed: completed)")
  • #242 "task: Add "radioGroup" form tag lib (closed: completed)")
  • #323 "task: Add "checkboxGroup" form tag lib (closed: completed)") and
  • #354 "task: Add "bind" tag to form tag library (closed: fixed)").
Clone this wiki locally