Changes to attributeCollection in 8.0.1

This post is more than 2 years old.

Ok, now that you've all downloaded 8.0.1 (in the last 5 minutes) and had a chance to play with it, I'm going to do a few blog entries about some of the new features in 8.0.1. ColdFusion 8 added the ability to use attributeCollection to ColdFusion built in tags. In case you never played with that feature (it's been around for a while in custom tags and cfinvoke), it allows you to dynamic define attributes for a tag. Consider:

<cfset s = structNew()> <cfset s.file = expandPath("./test.cfm")> <cfset s.action = "read"> <cfset s.variable = "r">

<cffile attributeCollection="#s#"> <cfoutput>#htmlCodeFormat(r)#</cfoutput>

This can be useful when you have to do different types of operations based on your business logic. It can save you from writing a lot of CFIF statements. For example, consider cfmail. You could dynamically add security attributes (for the server) instead of having to provide it in the core tag.

Ok - so that's ColdFusion 8. CF 8.0.1 expands on this by allowing you to add any attribute. So for example:

<cfset s = structNew()> <cfset s.file = expandPath("./test.cfm")> <cfset s.action = "read"> <cfset s.variable = "r"> <cfset s.frankie = "goestohollywood">

<cffile attributeCollection="#s#"> <cfoutput>#htmlCodeFormat(r)#</cfoutput>

Obviously frankie is not a valid attribute to cffile, but in 8.0.1, this will be ignored when passed through attributeCollection. You can disable this in the ColdFusion Admini, or in Application.cfc, and even in the structure itself.

So why would you do this? You may have common attributes that you want to share in a structure and pass to multiple tags.

Now I have to admit - when I first heard of this feature, I fought against it. I thought it was a bad idea. I was overruled (in a big way ;) so I'm curious to see what others think. I'm definitely more open to it now - but while I've used attributeCollection in the past, I haven't used it much at all yet in core CF tags, so this isn't a big deal to me now.

Anyone planning on using this?

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by James Allen posted on 4/4/2008 at 2:22 PM

I'll definetely keep this in mind now that it's available. I love the ability to configure custom params but only have one call of the actual CF tag. Before it was a case of either having a default variable set or lots of silly CFIF's and multiple tag calls.

I use attributeCollection quite a lot in my Services and Gateways so this will fit nicely into the arsenal of code options. Quite a flexible little feature.

Comment 2 by Shimju David posted on 4/4/2008 at 3:36 PM

Apparently, don't see any use of custom attribute for me. But Ray, thanks for noticing me the ability to use attributeCollection to ColdFusion built-in tags which was unknown to me.

Comment 3 by Ben Davies posted on 4/4/2008 at 3:58 PM

I can't think of any use cases off the top of my head. The original feature is great, since sometimes you don't know in advance if a particular attribute will be needed, which, as James and yourself have pointed out, can result in some silly IF statements.

Being able to pass in arbitrary attributes strikes me as a bit dangerous though. For example I always misspell variable 'varaible' when I type - and when I do it is nice to know that I did!

Can you specify an attribute AND include an argumentCollection struct? If so, if you repeat an argument name, which takes precedence?

I am subscribing to see if anyone comes up with any interesting use cases.

Comment 4 by Raymond Camden posted on 4/4/2008 at 4:23 PM

@Ben- No, unlike custom tags, it has to be all or nothing (afaik, haven't had coffee yet).

Comment 5 by Jason Delmore posted on 4/4/2008 at 5:20 PM

You CAN specify a collection and an Attribute and the attribute on the tag wins! :)

So...
<cfset myquerysettings.datasource= "MyMySQLDB"/>
<cfset myquerysettings.username = "foo"/>
<cfset myquerysettings.password= "bar"/>
<cfset myquerysettings.mypersonalattribute= "I like MySQL"/>

<cfquery attributeCollection="MyMySQLDB" password="password2">
Select * from users
</cfquery>

I have been the big proponent of this little feature because it allows CF tags to behave like UDFs (you can pass in extra stuff and those "just work" too).

So, what's another use case?

<cffunction name="cfmail">
<cfmail attributeCollection="#arguments#">
#arguments.body#
</cfmail>
</cffunction>

<cfscript>
mailparams.to = "foo@bar.com";
mailparams.from = "baz@foo.org";
mailparams.subject = "cfmail in cfscript";
mailparams.body = "You can create UDFs for tags that are forward compatible!"
</cfscript>

There are a bunch of other useful use case... creating defaults for tags in your application, storing metadata in objects and passing the entire object to a various tags... etc.

My main thing is that I wanted it to work like a user defined function, which allows extra stuff too. :)

Note: if you just use the attributes, these are still all validated for typos, so if you're worried about fat fingering... don't use this. :)

Let us know if you run into other cool uses!
Jason

Comment 6 by Jason Delmore posted on 4/4/2008 at 5:32 PM

Oh... I forgot..

<cfscript>
cfmail(mailparams);
</cfscript>

Not bad huh? :)

Jason

Comment 7 by Raymond Camden posted on 4/4/2008 at 5:34 PM

Jason - I forget. Was the ability to mix both inline and attributeCollection added in 801? I know the 'any arg you want' was added, but specifically the mix.

Comment 8 by Jason Delmore posted on 4/4/2008 at 6:02 PM

Having both the collection and a tag attribute, mix-n-match if you prefer :), was added with 8.0.1.

:)
Jason

Comment 9 by Ben Davies posted on 4/4/2008 at 8:55 PM

@Jason

You Wrote:
-----------------
Oh... I forgot..

<cfscript>
cfmail(mailparams);
</cfscript>
-----------------

We can *call* tags like a UDF? (!?!?!)
Any tag?

That can't be right... can it?
!!!

Comment 10 by Raymond Camden posted on 4/4/2008 at 8:58 PM

Nope. You would have to write a tag for it. But your udf would be very simple.

<cffunction name="cfmail">
<cfmail attributeCollection=arguments>
</cffunction>

Comment 11 by Ben Davies posted on 4/4/2008 at 9:04 PM

Ah I See. I nearly fell off my chair then.

Comment 12 by Misty posted on 7/3/2012 at 11:53 AM

Hey Ray, I am using this in my one of the custom tags and i am passing the value from the calling template as:

<cf_call mailing="{to='i@i.com',server='this.thisdomaijn.com',type='html',from='me@me.com'}">

now in my call.cfm custm tag i am using it like this

<cfmail attributecollection = "#attributes.call#">

it is giving me this error

The attributeCollection attribute in the cfmail tag can only be a structure.

Comment 13 by Misty posted on 7/3/2012 at 11:56 AM

I am getting this Error:

The attributeCollection attribute in the cfmail tag can only be a structure.

<cf_call ckmail="{to='test@test.com',from='test@test.com',subject='Error reported',mailserver='mail.domain.com',username='1234',password='tested'}">
in the custom tag call.cfm i have the following

<cfmail attributecollection = "#attributes.ckmail#">

Comment 14 by Raymond Camden posted on 7/3/2012 at 9:16 PM

You passed a string. To make that 'real' CF variable, try wrapping the {} with #.

Comment 15 by Misty posted on 7/3/2012 at 9:19 PM

i did not get it, can you please write the example as of how we are saying it to be done!

Comment 16 by Raymond Camden posted on 7/3/2012 at 9:20 PM

Instead of foo="{....}" do foo="#{...}#"

Comment 17 by Misty posted on 7/3/2012 at 9:52 PM

ok, now that did resolved but now mails are not coming

Comment 18 by Raymond Camden posted on 7/3/2012 at 9:55 PM

Um - but how am I supposed to know? You are using a custom tag called "call" - I have no idea what that is.

Comment 19 by Raymond Camden posted on 7/3/2012 at 9:55 PM

Oh sorry - I see where you say you use cfmail. Best thing to do is check your CF mail logs.

Comment 20 by Misty posted on 7/3/2012 at 10:00 PM

ok, i got it, i checked it in logs, mail is there, might be some server authentication issue, the issue is now resolved, Thanks Ray as always

Comment 21 by Misty posted on 7/4/2012 at 11:23 AM

Ok, now here is the question, tested on CF9 and it worked, Now Testing on CF 8.0.1, It failed miserably

<cf_call ckmail="#{to='test@test.com',from='test@test.com',subject='Error reported',mailserver='mail.domain.com',username='1234',password='tested'}#">
in the custom tag call.cfm i have the following
<cfparam name="attributes.ckmail" default="">
<cfmail attributecollection = "#attributes.ckmail#">

Error I am getting

Invalid CFML construct found on line 11 at column 18.
ColdFusion was looking at the following text:
{

Comment 22 by Raymond Camden posted on 7/4/2012 at 5:51 PM

You can't use that syntax in that way in CF8. Simply make a structure the 'old' way and pass it.