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.
Archived Comments
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.
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.
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.
I do the same as well. All my variables used within the template are always located under (LOCAL.templateInfo).
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.
That's slick as crap. Thanks Tony.