Tip: cfsavecontent and cfinclude within script based CFCs

This post is more than 2 years old.

Ok, so I know that I've said (many times) that including layout in a CFC is generally a bad idea. I still think it is. But like most rules there are always exceptions. Normally this wouldn't be a big deal, but HTML and JavaScript within a script based component is - well - it's ugly. Here is an example:

case "textbox": { return s & '<input type="text" name="#arguments.name#" value="#currentValue#">'; }

This simple example works, but more complex HTML gets messier. I could have switched the component over to tags. It's not like that would be the end of the world! But then I remember - you can use savecontent within script based cfcs. So instead of the inline HTML you see above, I now use:

case "event date": { savecontent variable="s" { include "render/eventdate.cfm"; } return s; }

Woot. I wish I had remembered this when I began the project, but I'm guessing I'll be getting used to ColdFusion 9 syntax until right around the release of ColdFusion 10.

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 Daniel Budde posted on 12/23/2009 at 7:09 PM

Although, I am not on CF9 yet, I have ran into this in the past when I wanted to e-mail template based reports from within my CFC. The reports already existed as HTML templates within the application, so the easy fix was to use <cfsavecontent> with a <cfinclude>.

It always makes me feel a little bad to have to break encapsulation, but as you say, there are those exceptions to the rule. I always just comment them well and since they are few and far between, they have just never caused any trouble.

Comment 2 by Tony Nelson posted on 12/23/2009 at 8:34 PM

You'll want to be careful when using .cfm mixins inside singleton components to make sure any variables declared within the mixin are thread-safe.

Comment 3 by Raymond Camden posted on 12/23/2009 at 8:54 PM

Agreed. I'm forcing myself to use local.x for all variables. I normally do NOT like local.foo, I just var scope, but for this component I'm using it as a way to ensure I'm always local.

Comment 4 by Daniel Budde posted on 12/23/2009 at 8:59 PM

I do the same as well. All my variables used within the template are always located under (LOCAL.templateInfo).

Comment 5 by Tony Nelson posted on 12/23/2009 at 9:31 PM

If you don't want to have to use local.x everywhere, you could create a small Include.cfc proxy for including templates.

case "event date": {
return new Include("render/eventdate.cfm",arguments);
}

Include.cfc:
component {
public string function init(template, params) {
structDelete(variables, "init");
structDelete(variables, "this");
structAppend(variables, arguments.params);
savecontent variable="local.html" {
include arguments.template;
}
return local.html;
}
}

Now any variables declared inside render/eventdate.cfm won't bleed into your component.

Comment 6 by Raymond Camden posted on 12/23/2009 at 9:32 PM

That's slick as crap. Thanks Tony.