coldfusionCFLOOP How-To

Remarks

Big thanks to

Looping through a collection using CFML tags.

<!--- Define collection --->
<cfset attributes = {
  "name": "Sales",
  "type": "text",
  "value": "Connection"
}>

<!--- 
  cfloop tag with attribute collection can be used to 
  loop through the elements of a structure
--->
<cfloop collection=#attributes# item="attribute">
  <cfoutput>
    Key : #attribute#, Value : #attributes[attribute]#
  </cfoutput>
</cfloop>

Looping through a collection using CFSCRIPT.

<cfscript>
  /*define collection*/
  attributes = {
    "name": "Sales",
    "type": "text",
    "value": "Connection"
  };
  for(attribute in attributes){
    /* attribute variable will contain the key name of each key value pair in loop */
    WriteOutput('Key : ' & attribute & ', Value : ' & attributes[attribute] & '<br/>');
  }
</cfscript>

Index

Parameters

AttributeRequiredTypeDefaultDescription
indextruestringVariable name for the loop's index. Defaults to the variables scope.
fromtruenumericStarting value for the index.
totruenumericEnding value for the index.
stepfalsenumeric1Value by which to increase or decrease the index per iteration.

Basic index loop

Final value of x is 10.

<!--- Tags --->
<cfoutput>
    <cfloop index="x" from="1" to="10">
        <li>#x#</li>
    </cfloop>
</cfoutput>
<!--- cfscript --->
<cfscript>
    for (x = 1; x <= 10; x++) {
        writeOutput('<li>' & x & '</li>');
    }
</cfscript>
<!--- HTML Output --->
 - 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10

Increase step to 2

Final value of x is 11.

<!--- Tags --->
<cfoutput>
    <cfloop index="x" from="1" to="10" step="2">
        <li>#x#</li>
    </cfloop>
</cfoutput>
<!--- cfscript --->
<cfscript>
    for (x = 1; x <= 10; x += 2) {
        writeOutput('<li>' & x & '</li>');
    }
</cfscript>
<!--- HTML Output --->
 - 1
 - 3
 - 5
 - 7
 - 9

Decrement step by 1

Final value of x is 0.

<!--- Tags --->
<cfoutput>
    <cfloop index="x" from="10" to="1" step="-1">
        <li>#x#</li>
    </cfloop>
</cfoutput>
<!--- cfscript --->
<cfscript>
    for (x = 10; x > 0; x--) {
        writeOutput('<li>' & x & '</li>');
    }
</cfscript>
<!--- HTML Output --->
 - 10
 - 9
 - 8
 - 7
 - 6
 - 5
 - 4
 - 3
 - 2
 - 1

CFLoop in a Function

Make sure to var or local scope the index inside a function. Foo() returns 11.

<!--- var scope --->
<cffunction name="foo" access="public" output="false" returntype="numeric">
    <cfset var x = 0 />
    <cfloop index="x" from="1" to="10" step="1">
        <cfset x++ />
    </cfloop>
    <cfreturn x />
</cffunction>

<!--- Local scope --->
<cffunction name="foo" access="public" output="false" returntype="numeric">
    <cfloop index="local.x" from="1" to="10" step="1">
        <cfset local.x++ />
    </cfloop>
    <cfreturn local.x />
</cffunction>

ColdFusion 11 through current

The cfscript function cfloop has no support for index as a stand alone counter mechanism.

Condition

Tag syntax

Parameters

AttributeRequiredTypeDefaultDescription
conditiontruestringCondition that manages the loop. Cannot contain math symbols like <, > or =. Must use ColdFusion text implementations like less than, lt, greater than, gt, equals or eq.

Final value of x is 5.

<cfset x = 0 />
<cfoutput>
    <cfloop condition="x LT 5">
        <cfset x++ />
        <li>#x#</li>
    </cfloop>
</cfoutput>

Generated HTML

This will also have a line break between each line of HTML.

<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>

CFScript

Previous to ColdFusion 8

<cfscript>
x = 0;
while (x LT 5) {
    x = x + 1;
    writeOutput('<li>' & x & '</li>');
}
</cfscript>

ColdFusion 8 through current

<cfscript>
x = 0;
while (x LT 5) {
    x = x++;
    writeOutput('<li>' & x & '</li>');
}
</cfscript>

ColdFusion 11 through current

The cfscript function cfloop has no support for condition.

Generated HTML

Notice that the cfscript output is all on one line.

<li>one</li><li>two</li><li>three</li><li>four</li>

Date or time range

Example for date or time range.

Query

Consider the table dbo.state_zip, which contains the columns city, statecode and zipcode and has over 80,000 records.

Parameters

AttributeRequiredTypeDefaultDescription
querytruestringThe variable name of a query object.
startrowfalsenumericThe starting row index of the query object.
endrowfalsenumericThe ending row index of the query object.
groupfalsestringThe query column name on which to group records.

Example query

<cfquery name="geo" datasource="reotrans-dev">
    SELECT city, stateCode, zipCode
    FROM dbo.state_zip
</cfquery>

Tag syntax

Using the query object geo as the source for cfloop. Since the table dbo.state_zip has so many records, the HTML generated will take quite some time. This example shows only the first 20 records' worth of HTML.

<cfoutput>
    <ul>
    <cfloop query="geo">
        <!--- Scope the column names with the query name. --->
        <li>#geo.city# | #geo.stateCode# | #geo.zipCode#</li>
    </cfloop>
    </ul>
</cfoutput>

Generated HTML

<ul>
    <li>100 PALMS | CA | 92274</li>
    <li>1000 PALMS | CA | 92276</li>
    <li>12 MILE | IN | 46988</li>
    <li>1ST NATIONAL BANK OF OMAHA | NE | 68197</li>
    <li>29 PALMS | CA | 92277</li>
    <li>29 PALMS | CA | 92278</li>
    <li>3 STATE FARM PLAZA | IL | 61710</li>
    <li>3 STATE FARM PLAZA | IL | 61791</li>
    <li>30TH STREET | PA | 19104</li>
    <li>3M CORP | MN | 55144</li>
    <li>65TH INFANTRY | PR | 00923</li>
    <li>65TH INFANTRY | PR | 00924</li>
    <li>65TH INFANTRY | PR | 00929</li>
    <li>65TH INFANTRY | PR | 00936</li>
    <li>7 CORNERS | VA | 22044</li>
    <li>88 | KY | 42130</li>
    <li>9 MILE POINT | LA | 70094</li>
    <li>A A R P INS | PA | 19187</li>    
    <li>A A R P PHARMACY | CT | 06167</li>
    <li>A H MCCOY FEDERAL BLDG | MS | 39269</li>
</ul>

Limiting output to specific rows

To limit the query's output to a specific range of rows, specify startrow and endrow.

<cfloop query="geo" startrow="100" endrow="150">
    <li>#geo.city# | #geo.stateCode# | #geo.zipCode#</li>
</cfloop>

Grouping Output

In the example data, the same state listed multiple times in relation to the multiple cities that are associated to each state. You can also see the same city listed multiple times in relation to the multiple zip codes associated to each city.

Let's group the output by state first. Notice the 2nd instance of cfloop wrapped around the content that will be output under the stateCode grouped content.

<cfoutput>
    <ul>
    <cfloop query="geo" group="stateCode">
        <!--- Scope the column names with the query name. --->
        <li>#geo.stateCode#
            <ul>
                <cfloop>
                    <li>#geo.city# | #geo.zipCode#</li>
                </cfloop>
            </ul>
        </li>
    </cfloop>
    </ul>
</cfoutput>

Generated HTML (extract) from one grouped cfloop tag.

<ul>
    <li>AK
        <ul>
            <li>KONGIGANAK | 99545</li>
            <li>ADAK | 99546</li>
            <li>ATKA | 99547</li>
            <!-- etc. -->
        </ul>
    </li>
    <li>AL
        <ul>
            <li>ALEX CITY | 35010</li>
            <li>ALEXANDER CITY | 35010</li>
            <li>ALEX CITY | 35011</li>
            <!-- etc. -->
        </ul>
    </li>
    <!-- etc. -->
</ul>

Finally, let's group the output by stateCode, then by city in order to see all the zipCode entries per city. Notice the 2nd cfloop is now grouped by city and a 3rd cfloop exists to output the zipCode data.

<cfoutput>
    <ul>
    <cfloop query="geo" group="stateCode">
        <li>#geo.stateCode#
            <ul>
            <cfloop group="city">
                <li>#geo.city#
                    <ul>
                        <cfloop>
                            <li>#geo.zipCode#</li>
                        </cfloop>
                    </ul>
                </li>
            </cfloop>
            </ul>
        </li>
    </cfloop>
    </ul>
</cfoutput>

Generated HTML (extract) from two grouped cfloop tags.

<ul>
    <li>AK
        <ul>
            <li>ADAK
                <ul>
                    <li>99546</li>
                    <li>99571</li>
                </ul>
            </li>
            <li>AKHIOK
                <ul>
                    <li>99615</li>
                </ul>
            </li>
            <!--- etc. --->
            <li>BARROW
                <ul>
                    <li>99723</li>
                    <li>99759</li>
                    <li>99789</li>
                    <li>99791</li>
                </ul>
            </li>
            <!--- etc. --->
        </ul>
    </li>
    <!--- stateCodes etc. --->
</ul>

CFScript

ColdFusion 6 (MX) though current

<cfscript>
    for (x = 1; x LTE geo.recordcount; x = x + 1) {
        writeOutput( '<li>' & geo.city[x] & ' | ' & 
            geo.stateCode[x] & ' | ' & geo.zipCode[x] & '</li>');
    }
</cfscript>

ColdFusion 8 though current

<cfscript>
    for (x = 1; x <= geo.recordcount; x++) {
        writeOutput( '<li>' & geo.city[x] & ' | ' & 
            geo.stateCode[x] & ' | ' & geo.zipCode[x] & '</li>');
    }
</cfscript>

ColdFusion 10 though current

With the FOR IN syntax, x is a query row object, not the row index.

<cfscript>
    for (x in geo) {
        writeOutput( '<li>' & x.city & ' | ' & 
            x.stateCode & ' | ' & x.zipCode & '</li>');
    }
</cfscript>

ColdFusion 11 though current

ColdFusion 11 allows most tags to be written as cfscript.

<cfscript>
    cfloop(query: geo, startrow: 1, endrow: 2) {
        writeOutput( '<li>' & geo.city & ' | ' & 
            geo.stateCode & ' | ' & geo.zipCode & '</li>');
    }
</cfscript>

With group.

<cfscript>
    cfloop(query: geo, group: 'city') {
        writeOutput( '<li>' & geo.city & '<ul>');
        cfloop() { // no arguments, just as in the tag syntax.
            writeOutput('<li>'  & geo.zipCode & '</li>');
        }
        writeOutput('</ul></li>');
    }
</cfscript>

List

Consider this list:

<cfset foo = "one,two,three,four" />

Tag syntax

Parameters

AttributeRequiredDefaultDescription
listtrueA list object. The variable must be evaluated (wrapped with ##)
indextrueThe current element of the list.
<cfoutput>
    <cfloop list="#foo#" index="x">
        <li>#x#</li>
    </cfloop>
</cfoutput>

Generated HTML

This will also have a line break between each line of HTML.

<li>one</li>
<li>two</li>
<li>three</li>
<li>four</li>

CFScript

Previous to ColdFusion 8

<cfscript>
    for (x = 1; x LTE listLen(foo); x = x + 1) {
        writeOutput("<li>" & listGetAt(foo, x) & "</li>");
    }
</cfscript>

ColdFusion 8 through current

<cfscript>
    for (x = 1; x <= listLen(foo); x++) {
        writeOutput("<li>" & listGetAt(foo, x) & "</li>");
    }
</cfscript>

ColdFusion 9 through current

<cfscript>
    for (x in foo) {
        writeOutput("<li>" & x & "</li>");
    }
</cfscript>

ColdFusion 11 through current

The cfscript function cfloop has no support for list.

Generated HTML

Notice that the cfscript output is all on one line.

<li>one</li><li>two</li><li>three</li><li>four</li>

Array

The ability to directly use an array object with cfloop was added in ColdFusion 8.

Consider this array;

<cfset aFoo = [
    "one"
    , "two"
    , "three"
    , "four"
] />

Tag syntax

ColdFusion 8 through current

Using the attribute index by itself.

Parameters

AttributeRequiredDefaultDescription
arraytrueAn array object. The variable must be evaluated (wrapped with ##)
indextrueThe current element of the array.
<cfoutput>
    <cfloop array="#aFoo#" index="x">
        <li>#x#</li>
    </cfloop>
</cfoutput>

Generated HTML

This will also have a line break between each line of HTML.

<li>one</li>
<li>two</li>
<li>three</li>
<li>four</li>

ColdFusion 2016 through current

The attribute item changes the behavior of cfloop as of Coldfusion 2016.

Using the attribute item instead of or in addition to index.

Parameters

AttributeRequiredDefaultDescription
arraytrueAn array object. The variable must be evaluated (wrapped with ##)
itemtrueThe current element of the array.
indexfalseThe current index of the array.
<cfoutput>
    <cfloop array="#aFoo#" item="x" index="y">
        <li>#x# | #y#</li>
    </cfloop>
</cfoutput>

Generated HTML

This will also have a line break between each line of HTML.

<li>one | 1</li>
<li>two | 2</li>
<li>three | 3</li>
<li>four | 4</li>

CFScript

Previous to ColdFusion 8

<cfscript>
for (i = 1; x LTE arrayLen(aFoo); i = i + 1) {
    writeOutput("<li>" & aFoo[i] & "</li>");
}
</cfscript>

ColdFusion 8 through current

<cfscript>
for (i = 1; i <= arrayLen(aFoo); i = i++) {
    writeOutput("<li>" & aFoo[i] & "</li>");
}
</cfscript>

ColdFusion 9 through current

With the FOR IN syntax, x is the current array element, not the array index.

<cfscript>
for (x in aFoo) {
    writeOutput("<li>" & x & "</li>");
}
</cfscript>

ColdFusion 11 through current

The cfscript function cfloop has no support for array.

Generated HTML

Notice that the cfscript output is all on one line.

<li>one</li><li>two</li><li>three</li><li>four</li>

File

<cfloop list="#myFile#" index="FileItem" delimiters="#chr(10)##chr(13)#">
  <cfoutput>
   #FileItem#<br />
 </cfoutput>
</cfloop>

Structure

Consider this structure:

<cfset stFoo = {
    a = "one"
    , b = "two"
    , c = "three"
    , d = "foue"
} />

Tag syntax

Parameters

Notice the use of the attribute item instead of index.

AttributeRequiredTypeDefaultDescription
collectiontruestructureA struct object. The variable must be evaluated (wrapped with ##).
itemtruestringThe current structure key,

Using Structure Functions

<cfoutput>
    <cfloop collection="#stFoo#" item="x">
        <li>#structFind(stFoo, x)#</li>
    </cfloop>
</cfoutput>

Implicit Structure Syntax

<cfoutput>
    <cfloop collection="#stFoo#" item="x">
        <li>#stFoo[x]#</li>
    </cfloop>
</cfoutput>

Generated HTML

This will also have a line break between each line of HTML.

<li>one</li>
<li>two</li>
<li>three</li>
<li>four</li>

CFScript

With the FOR IN syntax, x is a key of the structure object.

Output the structure's keys

<cfscript>
    for (x in stFoo) {
        writeOutput("<li>" & x & "</li>");
    }
</cfscript>

Generated HTML

<li>A</li><li>B</li><li>C</li><li>D</li>

Output the value of the structure's keys

Using Structure Functions

<cfscript>
    for (x in stFoo) {
        writeOutput("<li>" & structFind(stFoo, x) & "</li>");
    }
</cfscript>

Implicit Structure Syntax

<cfscript>
    for (x in stFoo) {
        writeOutput("<li>" & stFoo[x] & "</li>");
    }
</cfscript>

ColdFusion 11 through current

The cfscript function cfloop has no support for collection.

Generated HTML

Notice that the cfscript output is all on one line.

<li>one</li><li>two</li><li>three</li><li>four</li>

Index Loop

Use the from and to attributes to specify how many iterations should occur. The (optional) step attribute allows you to determine how big the increments will be.

<cfloop from="1" to="10" index="i" step="2">
    <cfoutput>
        #i#<br />
    </cfoutput>
</cfloop>

Conditional Loop

You use the condition attribute to specify the condition to use.

<cfset myVar=false>
<cfloop condition="myVar eq false">
    <cfoutput>
    myVar = <b>#myVar#</b>  (still in loop)<br />
 </cfoutput>
    <cfif RandRange(1,10) eq 10>
        <cfset myVar="true">
    </cfif>
</cfloop>
<cfoutput>
    myVar = <b>#myVar#</b> (loop has finished)
</cfoutput>

Query Loop

You can loop over the results of a ColdFusion query.

<cfquery name="getMovies" datasource="Entertainment">
    select top 4 movieName
    from Movies
</cfquery>
<cfloop query="getMovies">
    #movieName#
</cfloop>

List Loop

You can use the (optional) delimiters attribute to specify which characters are used as separators in the list.

<cfloop list="ColdFusion,HTML;XML" index="ListItem" delimiters=",;">
    <cfoutput>
        #ListItem#<br />
    </cfoutput>
</cfloop>

File Loop

You can loop over a file.

<cfloop file="#myFile#" index="line">
    <cfoutput>
        #line#<br />
    </cfoutput>
</cfloop>

COM Collection/Structure Loops

You can loop over a Structure or COM collection.

<cfset myBooks = StructNew()>
<cfset myVariable = StructInsert(myBooks,"ColdFusion","ColdFusion MX Bible")>
<cfset myVariable = StructInsert(myBooks,"HTML","HTML Visual QuickStart")>
<cfset myVariable = StructInsert(myBooks,"XML","Inside XML")>
<cfloop collection="#myBooks#" item="subject">
    <cfoutput>
        <b>#subject#:</b> #StructFind(myBooks,subject)#<br />
    </cfoutput>
</cfloop>