I Wish: ColdFusion Custom Tag Query Looping

Posted November 3, 2008 at 8:54 PM by Ben Nadel

Tags: ColdFusion

I'm not sure why I want this to work, but there's something about it that would just be neat. I think if this could be done, it would open up potentially interesting ways to loop over a ColdFusion query in custom ways that still feel very natural. I was trying to do something like this:

  • <cfswitch expression="#THISTAG.ExecutionMode#">
  • <cfcase value="Start">
  •  
  • <!--- Param the query name. --->
  • <cfparam
  • name="ATTRIBUTES.Query"
  • type="variablename"
  • />
  •  
  • <!--- Default the loop index. --->
  • <cfset VARIABLES.LoopIndex = 1 />
  •  
  • </cfcase>
  • <cfcase value="End">
  •  
  • <!--- Check to see if loop index is not too high. --->
  • <cfif (VARIABLES.LoopIndex LT CALLER[ ATTRIBUTES.Query ].RecordCount)>
  •  
  • <!--- Increment the index. --->
  • <cfset VARIABLES.LoopIndex++ />
  •  
  • <!--- Loop over *only* the selected row. --->
  • <cfloop
  • query="CALLER.#ATTRIBUTES.Query#"
  • startrow="#VARIABLES.LoopIndex#"
  • endrow="#VARIABLES.LoopIndex#">
  •  
  • <!--- Run the body of the tag again. --->
  • <cfexit method="loop" />
  •  
  • </cfloop>
  •  
  • </cfif>
  •  
  • </cfcase>
  • </cfswitch>

Handling the first row would obviously be difficult - I think it would have to be row 1. But, in the end of the tag, I'm trying to re-execute the ColdFusion custom tag body while in the context of the current query iteration (such that the calling page would think that it was actually in the #CurrentRow# of the query). This doesn't actually work as the moment you exit out of the custom tag, you lose the query context.

Anyway, not sure if anyone ever tried to do this or found a way to do it. Just having some fun on a Monday night, trying to think outside of the box.



Reader Comments

ike
Nov 3, 2008 at 9:20 PM // reply »
78 Comments

Yeah, that's an interesting thought...

I would think you could do that, but you would have to be willing to be a little sloppy with the encapsulation of the custom tag. Which some people are okay with and others aren't. But if you were to create say a request variable to hold the current index, then you could increment it on each pass through the tag. The problem you'd run into is if you wanted to call the tag more than once. You could clear the request variable after the closing tag, but you still wouldn't be able to nest them.

I would pass the query into the tag as an object though, instead of passing in the name of the query and referencing the caller scope. I gather it would retain the query through each pass.


Nov 4, 2008 at 11:31 AM // reply »
11,243 Comments

@Ike,

I don't think having a request-based value would help. You'd still have the problem of having the query be in the appropriate loop index from the CALLER standpoint. Really, the ultimate goal would be to supply an arbitrary "order index" and have the calling page not have to worry about it or use notation like:

query[ column ][ row ]

... but rather:

query.column

... no matter what iteration we are on.


ike
Nov 4, 2008 at 1:28 PM // reply »
78 Comments

Actually come to think of it ColdFusion 9 will add the feature that will make the equivalent of this available... the cfcontinue tag -- then you can just cfloop with the query and cfcontinue instead of dealing with the custom tag


ike
Nov 4, 2008 at 1:31 PM // reply »
78 Comments

Or not... since the cfexit is in the end tag...

okay, backing up a bit, I'm not sure what the custom tag adds over a cfloop


Nov 4, 2008 at 1:38 PM // reply »
11,243 Comments

@Ike,

The custom tag adds the ability to order the query in a totally arbitrary way. I am not saying that I have any great use cases right now, but if the ability was there, perhaps I could come up with one. Image a loop tag that could loop over the query backwards without having to use explicit row indexing?


ike
Nov 4, 2008 at 3:11 PM // reply »
78 Comments

oh okay... like a step beyond what you can do with grouping.


Nov 4, 2008 at 3:12 PM // reply »
11,243 Comments

@Ike,

Yeah, exactly. Heck you could even make a version that loops over a query in a totally random order (just for yucks).


Nov 13, 2008 at 11:50 AM // reply »
12 Comments

What does that add that you can't get by changing the SQL statement?


Nov 13, 2008 at 12:55 PM // reply »
11,243 Comments

@Matt,

I think the idea here is not so much that the query could be changed to reflect the infinite type of custom looping - the idea here is that the query doesn't need to know about it. I know that might seem silly - why have a query that uses different sorting than the output, but if you think about all the logic that goes into it, I think it makes sense to abstract that out into its own black box.

Imagine a totally crazy scenario where one user can only display odd rows and one user can only display even rows. Is this the kind of logic that you want to building into your SQL statement (odd vs. even row logic)? Or is this something that you want to factor out into something else.

Remember, all of the logic in the custom tag *could* be moved into the calling page; but again, the idea here is we might want to make certain logic easily reusable.


Nov 13, 2008 at 1:19 PM // reply »
12 Comments

Okay, that makes sense. And along the same lines, the idea behind a SQL result set is that it's essentially an unordered set - ordering in a SQL statement is only done for convenience in a list. I'll have to think on this a bit.


ike
Nov 13, 2008 at 1:59 PM // reply »
78 Comments

Yeah, I think it's kind of difficult for folks (self included) to "click" with this idea because we can't think of any really practical use-cases that would serve as examples of why you might want this.

Seems like the only way to really achieve this is (at least currently) is to separate the content into an include file or something instead of the end-tag syntax. Although the end-tag syntax would be sort of ideal for this kind of thing because it would make it easier to use. XSLT also offers some options, but again that's moving to greater complexity.


Nov 13, 2008 at 2:09 PM // reply »
11,243 Comments

@Ike,

I agree, not that many use cases. The one that I actually had in mind when doing this was, or rather, how I ended up here, was displaying a datagrid that was listed alphabetically DOWN rather than Across:

[ A ][ C ][ D ]
[ A ][ D ][ E ]
[ B ][ D ][ E ]
[ B ][ D ][ E ]

Ideally, when outputting a query, you just want to do something like:

<cfloop query="qData">

<td>
. . . . #qData.value#
</td>

</cfloop>

If I had a query that came back alphabetically, I thought I could come up with a custom-tag way to display it using the above code even though the across-output would *not* be alphabetical.

Anyway, when I got to thinking like that, I thought it would be nice to have a custom tag that would allow me to somehow alter the order of query output in a more natural way.


ike
Nov 13, 2008 at 2:41 PM // reply »
78 Comments

Oh yeah, three-columns down in a grid is always a fidgety and annoying bit of code to write... You end up doing like end-row ceiling(recordcount/3) and then mathematically figure out the index of the values in columns 2 & 3 as you loop down...

<cfset rows = ceiling(qry.recordcount / 3) />

<cfoutput query="qry" startrow="1" maxrows="#rows#">

<tr>
<cfloop index="add" list="0,#rows#,#rows*2#">

<cfset x = currentrow + add />
<td>#qry.column[x]#</td>

</cfloop>
</tr>

</cfoutput>

Who wouldn't want an easier way of doing that?!


Nov 13, 2008 at 2:59 PM // reply »
11,243 Comments

@Ike,

I agree - everyone would want an easier way :)



Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 22, 2013 at 5:35 PM
Script Tags, jQuery, And Html(), Text() And Contents()
This is still an issue 2 years later. jQuery is supposed to remediate these cross browser issues, no? I have been unable to find any statement from the jQuery team calling this behavior "by de ... read »
May 22, 2013 at 12:44 PM
Ask Ben: Query Loop Inside CFScript Tags
In cf10, if you call a function that has: local.result = {}; local.result.msg = ""; local.svc = new query(); local.svc.setSQL("SELECT * FROM..."); local.obj = local.svc.exe ... read »
May 22, 2013 at 12:29 PM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Ben: What version of Java are you using? Also, did you test users.id to see what Java reports as the data type? I wonder if it's not a Java primitive data type, but getting returned as something ... read »
May 22, 2013 at 11:47 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Dana, Awesome - so it looks like this bug was fixed in ColdFusion 10. Thanks so much for double-checking that. ... read »
May 22, 2013 at 11:37 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
When I c&p and run on cf10, I get: Selected User IDs: 1,4 User 1 selected: YES - YES User 2 selected: NO - NO User 3 selected: NO - NO User 4 selected: YES - YES User 5 selected: NO - ... read »
May 22, 2013 at 11:27 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Tom, Good thought, but no dice. Both of these still exhibit the same behavior: users.id[ users.currentRow ] users[ "id" ][ users.currentRow ] It's just something whacky happening with ... read »
May 22, 2013 at 11:07 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
Could your problem be that "users.id" is actually an ARRAY, not a single value? Perhaps try it again with "users.id[1]" (I only have CF8 here at work). ... read »
May 22, 2013 at 7:52 AM
Nested Views, Routing, And Deep Linking With AngularJS
Hi, Just a quick thank you. As it happens, for my own purposes, the pending ui-router work being done in native angular is likely the one I'll adopt, but your exploration, code and documentation of ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools