CPCUG Monitor
Creating dynamic websites with ColdFusion
Part 4: Loops and Lists
by Michael Smith
What is ColdFusion
In this article we continue to look at what ColdFusion is
and how you can use it for dynamic website creation. We cover all the different
varieties of the loop tag and how ColdFusion makes list handling easy.
In case you missed the last article that introduced
ColdFusion, let me explain what it is. ColdFusion is a programming language
based on standard HTML (Hyper Text Markup Language) that is used to write
dynamic webpages. It lets you create pages on the fly that differ depending on
user input, database lookups, time of day or what ever other criteria you dream
up! ColdFusion pages consist of standard HTML tags such as <FONT SIZE=”+2”>
together with CFML (ColdFusion Markup Language) tags such as <CFQUERY>,
<CFIF>
and <CFLOOP>. ColdFusion was introduced by Allaire in 1996
and is currently on version 4.0
Looping in ColdFusion
Looping is a very powerful programming technique that lets
you repeat a set of instructions or display output over and over until one or
more conditions are met. ColdFusion implements looping with the <CFLOOP>
tag. Five different types of loops are available:
·
Index Loops
·
Conditional Loops
·
Looping over a Query
·
Looping over a List
·
Looping over a COM Collection or Structure
The type of loop is determined by the attributes of the
<CFLOOP> tag as I will explain in detail below.
Index loops
An index loop repeats for a number of times determined by a
range of numeric values. Index loops are commonly known as FOR loops, as in
"loop FOR this range of values." The general syntax is:
<CFLOOP INDEX="parameter_name"
FROM="beginning_value"
TO="ending_value"
STEP="increment">
HTML or CFML code
to repeat
</CFLOOP>
For example if we want
HTML list boxes of hours and minutes that go from 0 to 23 and 0 to 59
respectively we could use two CFLOOP tags as follows:
<SELECT NAME="Hour">
<CFLOOP INDEX="hour" FROM="0"
TO="23">
<CFOUTPUT>
<OPTION
VALUE="#hour#">#hour#
</CFOUTPUT>
</CFLOOP>
</SELECT>
:
<SELECT NAME="Minute">
<CFLOOP INDEX="minute"FROM ="0"
TO="59">
<CFOUTPUT>
<OPTION
VALUE="#minute#">#minute#
</CFOUTPUT>
</CFLOOP>
</SELECT>
This will result in two list boxes side by side, one with 24
items, the other with 60. If instead we had preferred one list box with all the
hours and minutes of the day (that is 1440 items!) we could instead have nested the loops:
<SELECT NAME="HourAndMinutes">
<CFLOOP INDEX="hour" FROM="0"
TO="23">
<CFLOOP
INDEX="minute" FROM="0" TO="59">
<CFOUTPUT>
<OPTION
VALUE="'#hour#:#minute#'">#hour#:#minute#
</CFOUTPUT>
</CFLOOP>
</CFLOOP>
</SELECT>
Notice how now we have enclosed the option value passed by
the form submit in single quotes. This is because we want to pass a string such
as '12:25' rather than just the number of hours and minutes separately. Also as
we left off the STEP parameter it defaults to a step size of one.
If you try the above code at home be prepared to wait a
little while as to be honest a list box with more than a thousand items in it
is not browser friendly and may either take a long time to display or crash
older browsers!
Conditional Loops
A conditional loop iterates over a set of instructions
while a given condition is TRUE. The exact number of times it repeats may not
be known when the code is written, so that is how it differs from an index
loop. However if you want to avoid your program running for ever in an infinite
loop you probably will want to change the condition every time the loop
iterates so that the condition does eventually evaluate as FALSE. Conditional
loops are commonly known as WHILE loops, as in “loop WHILE this condition is
true.”
Suppose we want to display a random number of horizontal
lines a page. One way to do this is to loop until a random number is greater
than a given number.
<CFSET StopIt = 0>
<CFLOOP CONDITION="StopIt LESS THAN OR EQUAL TO
5">
<CFSET StopIt
= RandRange(1,10)>
<HR>
</CFLOOP>
Can exit a loop with <CFBREAK>
Looping over a Query
A loop over a query repeats for every record in the query
record set. The CFLOOP results are just
like a CFOUTPUT. During each iteration of the loop, the columns of the current
row will be available for output. It
just runs slower.
Then why would you use CFLOOP instead of CFOUTPUT? The
advantage of looping over a query is that you can use CFML tags that are not
allowed in a CFOUTPUT. For example,
nested queries or email tags. The following example loops through a list of
email addresses, and for each person sends all messages corresponding to that
user’s security level.
<CFQUERY NAME="GetEmail"
DATASOURCE="Library">
SELECT Email ,
SecurityLevel
FROM Customer
</CFQUERY>
<CFLOOP QUERY="GetEmail">
<CFQUERY
NAME="GetText"
DATASOURCE="Library">
SELECT
EmailText, EmailSubject
FROM Messages
WHERE SecurityLevel = #GetEmail.SecurityLevel#
</CFQUERY>
<CFMAIL
QUERY="GetText"
TO="#GetEmail.Email#"
FROM="[email protected]"
SUBJECT="#GetText.EmailSubject#"
SERVER="smtp.mycompany.com">#GetText.EmailText#
</CFMAIL>
</CFLOOP>
In this example we are looping over customer email addresses
and depending on their security level querying for different email text and
subject line before emailing the message to them. If we replaced the outer
CFLOOP by a CFOUTPUT a ColdFusion error would result.
Looping over a List
Looping over a list runs a loop though any
typically comma delimited list of items you have. In a list loop, the INDEX
attribute specifies the name of a variable to receive the next element of the
list, and the LIST attribute holds a list or a variable containing a list.
Where does a comma-delimited list come from in your pages
you ask? A common source is a multi-select list box or check boxes in a
previous page. In our example we generate a list of state from a states table
in our database.
<CFQUERY NAME="StateNames"
DATASOURCE="Library">
SELECT State_ID, StateName
FROM States
</CFQUERY>
<FORM ACTION="example.cfm"
METHOD="Post">
<SELECT NAME="state" MULTIPLE>
<CFOUTPUT QUERY="StateNames">
<OPTION
VALUE="’#State_ID#’">#StateName#
</CFOUTPUT>
</SELECT>
<INPUT TYPE="submit"
VALUE="Submit">
</FORM>
When this form is submitted, it passes the selected
State_ID’s as a comma delimited list of state codes.
Having created our comma-delimited list of states the next
page processes the list:
<H2>The following states were selected</H2>
<CFSET extraSQL = ‘FALSE’>
<CFLOOP INDEX="ListElement"
LIST="#form.state#"
DELIMITERS=",">
<CFOUTPUT>#ListElement#</CFOUTPUT><BR>
<CFSET
extraSQL = extraSQL & “ OR State_ID
= ‘#PreserveSingleQuotes(ListElement)#’”>
</CFLOOP>
<CFQUERY NAME="GetCustomers"
DATASOURCE="Library">
SELECT *
FROM Customer
WHERE #PreserveSingleQuotes(extraSQL)#
</CFQUERY>
If the states selected are MD, VA and DC then the above code
will generate the following HTML:
<H2>The following states were selected</H2>
MD<BR>
VA<BR>
DC<BR>
And the query will contain the following SQL statement:
SELECT
*
FROM
Customer
WHERE
FALSE OR State_ID = ‘MD’ OR State_ID = ‘VA’ OR State_ID = ‘DC’
Notice that we use the initial value of FALSE for the
extraSQL variable so that the above code will still work whether the list is
empty or only contains one state. Preserve single quotes is required to prevent
the automatic doubling up of quote marks.
Although CFLOOP expects elements in the list to be
separated by commas by default, you are free to specify your own element
boundaries in the DELIMITER attribute.
You can even specify several alternative delimiters.
By the way if you are not trying to demonstrate how to use
loops then there is an easier way to code for the above query on a list of
states using the SQL IN clause.
SELECT *
FROM Customer
WHERE State_ID IN (#PreserveSingleQuotes(Form.state)#)
In our example above, the SQL statement sent to the database
would be:
SELECT
*
FROM
Customer
WHERE
State_ID IN (‘DC’,‘MD’,‘VA’)
Looping over a COM Collection or Structure
Although it is beyond the level of this article I should
also tell you that CFLOOP lets you loop both over a ColdFusion structure and
over a COM/DCOM collection object. For the curious a COM/DCOM collection object
is a set of similar items referenced as a group rather than individually. For
example, the group of open documents in an application is a type of
collection. A structure is a related
set of items or an associative
array. Or in other words, an array
whose index is not numeric but consists of arbitrary words.
Summary
In this article we learned about all the different varieties
of the <CFLOOP> tag for looping. We covered FOR loops, WHILE loops, query
loops, list loops, COM /structure loops. We also explained how lists can be
used in your pages.
To Learn More
You can download a free 30 day-evaluation version of
ColdFusion from Allaire or request a free eval CD-ROM from
the Allaire website http://www.allaire.com/
Allaire Corporation
1 Alewife Center
Cambridge, MA 02140
Tel: 617.761.2000 voice
Fax: 617.761.2001 fax
Toll Free: 888.939.2545
Email: [email protected]
Web: www.allaire.com
ColdFusion Resources
Allaire also maintains an extensive knowledge base and
tech support forums on their website.
CPCUG and TeraTech ColdFusion
Conference http://www.teratech.com/cfconf/
TeraTech maintains a ColdFusion code cuttings called
ColdCuts at http://www.teratech.com/ColdCuts/.
This page also has links to about a dozen ColdFusion white papers in the CF
Info Center.
The Maryland ColdFusion User Group meets the second
Tuesday of each month at Backstreets Cafe, 12352 Wilkins Avenue, Rockville. See http://www.cfug-md.org/ for details and
directions.
The DC ColdFusion User Group meets the first Wednesday
each month at Figleaf , 16th and P St NW, Washington DC. See the
DCCFUG page on http://www.figleaf.com/
for details and directions.
Bio
Michael Smith is president of TeraTech, a ten year old
Rockville Maryland based consulting company that specializes in ColdFusion,
Database and Visual Basic development. You can reach Michael at [email protected] or 301-424-3903.