|
Example: a dynamic shopping cart
The
following example dynamically creates and manipulates variable names without
using dynamic expression evaluation by using associative array notation.
You need to dynamically generate variable names in applications
such as shopping carts, where the required output is dynamically
generated and variable. In a shopping cart, you do not know in advance
the number of cart entries or their contents. Also, because you
are using a form, the action page only receives Form variables with
the names and values of the form fields.
The following example shows the shopping cart contents and lets
you edit your order and submit it. To simplify things, the example
automatically generates the shopping cart contents using CFScript
instead of having the user fill the cart. A more complete example
would populate a shopping cart as the user selected items. Similarly,
the example omits all business logic for committing and making the
order.
Create the formCreate a file in your editor.
<html>
<head>
<title>Shopping Cart</title>
</head>
<cfscript>
CartItems=4;
Cart = ArrayNew(1);
for ( i=1; i LE cartItems; i=i+1)
{
Cart[i]=StructNew();
Cart[i].ID=i;
Cart[i].Name="Product " & i;
Cart[i].SKU=i*100+(2*i*10)+(3*i);
Cart[i].Qty=3*i-2;
}
</cfscript>
<body>
Your shopping cart has the following items.<br>
You can change your order quantities.<br>
If you don't want any item, clear the item's check box.<br>
When you are ready to order, click submit.<br>
<br>
<cfform name="ShoppingCart" action="ShoppingCartAction.cfm" method="post">
<table>
<tr>
<td>Order?</td>
<td>Product</td>
<td>Code</td>
<td>Quantity</td>
</tr>
<cfloop index="i" from="1" to="#cartItems#">
<tr>
<cfset productName= "product_" & Cart[i].ID>
<cfset skuName= "sku_" & Cart[i].ID>
<cfset qtyname= "qty_" & Cart[i].ID>
<td><cfinput type="checkbox" name="itemID" value="#Cart[i].ID#" checked>
</td>
<td><cfinput type="text" name="#productName#" value="#Cart[i].Name#"
passThrough = "readonly = 'True'"></td>
<td><cfinput type="text" name="#skuName#" value="#Cart[i].SKU#"
passThrough = "readonly = 'True'"></td>
<td><cfinput type="text" name="#qtyName#" value="#Cart[i].Qty#">
</td>
</tr>
</cfloop>
</table>
<input type="submit" name="submit" value="submit">
</cfform>
</body>
</html>
Save the file as ShoppingCartForm.cfm.
Reviewing the codeThe following table describes the code:
Code
|
Description
|
<cfscript>
CartItems=4;
Cart = ArrayNew(1);
for ( i=1; i LE cartItems; i=i+1)
{
Cart[i]=StructNew();
Cart[i].ID=i;
Cart[i].Name="Product " & i;
Cart[i].SKU=i*100+(2*i*10)+(3*i);
Cart[i].Qty=3*i-2;
}
</cfscript>
|
Create a shopping cart as an array of structures,
with each structure containing the cart item ID, product name, SKU
number, and quantity ordered for one item in the cart. Populate
the shopping cart by looping CartItems times and setting the structure
variables to arbitrary values based on the loop counter. A real
application would set the Name, SKU, and Quantity values on other
pages.
|
<cfform name="ShoppingCart" action="ShoppingCartAction.cfm" method="post">
<table>
<tr>
<td>Order?</td>
<td>Product</td>
<td>Code</td>
<td>Quantity</td>
</tr>
|
Start the form and its embedded table. When
the user clicks the submit button, post the form data to the ShoppingCartAction.cfm
page.
The table formats the form neatly. The first table
row contains the column headers. Each following row has the data
for one cart item.
|
<cfloop index="i" from="1" to="#cartItems#">
<tr>
<cfset productName= "product_" & Cart[i].ID>
<cfset skuName= "sku_" & Cart[i].ID>
<cfset qtyname= "qty_" & Cart[i].ID>
<td><cfinput type="checkbox" name="itemID" value="#Cart[i].ID#" checked>
</td>
<td><cfinput type="text" name="#productName#" value="#Cart[i].Name#"
passThrough = "readonly = 'True'"></td>
<td><cfinput type="text" name="#skuName#" value="#Cart[i].SKU#"
passThrough = "readonly = 'True'"></td>
<td><cfinput type="text" name="#qtyName#" value="#Cart[i].Qty#">
</td>
</tr>
</cfloop>
</table>
|
Loop through the shopping cart entries to
generate the cart form dynamically. For each loop, generate variables
used for the form field name attributes by appending the cart item
ID (Cart[i].ID) to a field type identifier, such as "sku_".
Use
a single name, "itemID", for all check boxes. This way, the itemID value
posted to the action page is a list of all the check box field values. The
check box field value for each item is the cart item ID.
Each
column in a row contains a field for a cart item structure entry. The passthrough attribute
sets the product name and SKU fields to read only; note the use
of single-quotation marks. (For more information on the cfinput tag passthrough attribute,
see the CFML Reference.) The check boxes are selected by
default.
|
<input type="submit" name="submit" value="submit">
</cfform>
|
Create the Submit button and end the form.
|
Create the Action pageCreate a file in your editor.
Enter the following text:
<html>
<head>
<title>Your Order</title>
</head>
<body>
<cfif isDefined("Form.submit")>
<cfparam name="Form.itemID" default="">
<cfoutput>
You have ordered the following items:<br>
<br>
<cfloop index="i" list="#Form.itemID#">
ProductName: #Form["product_" & i]#<br>
Product Code: #Form["sku_" & i]#<br>
Quantity: #Form["qty_" & i]#<br>
<br>
</cfloop>
</cfoutput>
</cfif>
</body>
</html>
Save the file as ShoppingCartAction.cfm
Open ShoppingCartform.cfm in your browser, change the check
box and quantity values, and click Submit.
Reviewing the codeThe following table describes the code:
Code
|
Description
|
<cfif isDefined("Form.submit")>
|
Run the CFML on this page only if it is
called by submitting a form. This is not needed if the form and
action pages are separate, but is required if the form and action
page were one ColdFusion page.
|
<cfparam name="Form.itemID" default="">
|
Set the default Form.itemID to the empty
string. This prevents ColdFusion from displaying an error if the
user clears all check boxes before submitting the form (so no product
IDs are submitted).
|
<cfoutput>
You have ordered the following items:<br>
<br>
<cfloop index="i" list="#Form.itemID#">
ProductName: #Form["product_" & i]#<br>
Product Code: #Form["sku_" & i]#<br>
Quantity: #Form["qty_" & i]#<br>
<br>
</cfloop>
</cfoutput>
</cfif>
|
Display the name, SKU number, and quantity
for each ordered item.
The form page posts Form.itemID as
a list containing the value attributes of all the check boxes. These
attributes contain the shopping cart item IDs for the selected cart items.
Use the list values to index a loop that outputs each ordered item.
Use
associative array notation to access the Form scope as a structure
and use expressions in the array indexes to construct the form variable
names. The expressions consist of a string containing the field
name’s field type prefix (for example, "sku_"), concatenated with
the variable i, which contains the shopping cart ItemID number (which
is also the loop index variable).
|
|