Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
A demonstration of looping custom tags in ColdFusion. Part 3: table.cfm (
<!--- table.cfm --->
<cfif THISTAG.ExecutionMode EQ "Start">
param name=""; // no type checking, just existence checking
param name="attributes.headers" type="boolean" default=false;
param name="attributes.columnNames" type="string"; // this'll be treated as a list
currentRow = 1;
// work out how we handle the data
if (isQuery({
rows = getSizeOfQuery(;
getRow = getRowFromQuery; // note that's a function REFERENCE, not a function CALL
}else if (isArray({
rows = getSizeOfArray(;
getRow = getRowFromArray;
}else{ // xml
rows = getSizeOfXml(;
getRow = getRowFromXml;
headers = listToArray(attributes.columnNames);
// grab any extra attributes, and treat them as attributes of the table tag
otherAttributes = "";
for (attribute in attributes){
if (!listFindNoCase("data,headers,columnNames", attribute)){
otherAttributes &= ' #lcase(attribute)#="#attributes[attribute]#"';
<cfoutput><table #otherAttributes#></cfoutput>
<cfif attributes.headers>
<cfloop index="header" array="#headers#">
<cfset setCallerVars(, currentRow, getRow, attributes.columnNames)>
<cfelse> <!---end--->
<cfset currentRow++>
<cfif currentRow LE rows>
<cfset setCallerVars(, currentRow, getRow, attributes.columnNames)>
<cfexit method="loop">
<cfexit method="exittag">
// helper functions
// we need to do this logic twice, so refactor it
void function setCallerVars(data, row, getRow, columnNames){
var rowData = getRow(data, row, columnNames);
for (var col in listToArray(columnNames)){
caller[col] = rowData[col];
// how many rows
numeric function getSizeOfQuery(q){
return q.recordCount;
numeric function getSizeOfArray(a){
return arrayLen(a);
numeric function getSizeOfXml(x){
return arrayLen(xmlSearch(x, "/*/*"));
// get a row
struct function getRowFromQuery(query q, numeric i){
var row = {};
for (var col in listToArray(q.columnList)){
row[col] = q[col][i];
return row;
struct function getRowFromArray(array a, numeric i, string columnNames){
var row = {};
for (var col=1; col <= listLen(columnNames); col++){
row[listGetAt(columnNames, col)] = a[i][col];
return row;
struct function getRowFromXml(xml x, numeric i){
var row = {};
var xmlRow = xmlSearch(x, "/*/*[#i#]");
for (var col in xmlRow[1].xmlAttributes){
row[col] = xmlRow[1].xmlAttributes[col];
return row;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment