Skip to content

Instantly share code, notes, and snippets.

@bennadel
Created February 23, 2021 12:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bennadel/5b64949eeb8dc89ceeb0f4f0810e15d5 to your computer and use it in GitHub Desktop.
Save bennadel/5b64949eeb8dc89ceeb0f4f0810e15d5 to your computer and use it in GitHub Desktop.
Using ColdFusion Custom Tags To Create An HTML Email DSL In Lucee CFML 5.3.7.47, Part XI
<!--- Import custom tag libraries. --->
<cfimport prefix="core" taglib="./core/" />
<cfimport prefix="html" taglib="./core/html/" />
<cfimport prefix="ex12" taglib="./ex12/" />
<!--- // ------------------------------------------------------------------------- // --->
<!--- // ------------------------------------------------------------------------- // --->
<core:Email
subject="Providing values"
teaser="Borrowing more inversion of control ideas from Angular!">
<!---
The Provide tag sets up key-value pairs that are accessible to other ColdFusion
custom tags in the Email. This is just another way to provide data to lower-level
rendering abstractions. This approach will be useful for deeply-nested tags that
would otherwise require "prop drilling" in order to get data down several layers
of rendering. For example:
<ex12:Body> => <ex12:FooterLinks> => <html:a>
In order to get URLs down to the "footer links" component WITHOUT having to first
provide them to the "body" component as an intermediary, we can "provide" them
and then the "footer links" component can just reach for them directly.
--->
<core:Provide name="siteUrl" value="https://www.bennadel.com/" />
<core:Provide name="aboutUrl" value="https://www.bennadel.com/about" />
<core:Provide name="peopleUrl" value="https://www.bennadel.com/people" />
<ex12:Body>
<html:h1>
Providing deep values
</html:h1>
<html:p>
In <html:mark>Example 8</html:mark>, we looked at various ways to encapsulate
rendering details:
</html:p>
<html:ul>
<html:li>Using CFInclude.</html:li>
<html:li>Using tag attributes.</html:li>
<html:li>Using tag generated content.</html:li>
<html:li>Using multi-slot projection.</html:li>
</html:ul>
<html:p>
Now, I'd like to borrow <html:em>yet another</html:em> idea from Angular:
<html:mark>Providers</html:mark>. A provider just creates a key-value pair
that is subsequently accessible to every other ColdFusion custom tag in
the email rendering.
</html:p>
</ex12:Body>
</core:Email>
<cfscript>
// Define custom tag attributes.
param name="attributes.name" type="string";
param name="attributes.value" type="any";
// ------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------- //
switch ( thistag.executionMode ) {
case "start":
getBaseTagData( "cf_email" ).providers[ attributes.name ] = attributes.value;
// Make sure this tag has NO BODY.
exit method = "exitTag";
break;
}
</cfscript>
<cfswitch expression="#thistag.executionMode#">
<cfcase value="end">
<cfoutput>
<cfset email = getBaseTagData( "cf_email" ) />
<!---
In order to access the defined providers, I just have to reach up into
the base "email" tag and grab the Providers struct. The same way I do
for the theme data.
--->
<cfset theme = email.theme />
<cfset providers = email.providers />
<!--- ... truncated ... --->
<html:table width="#theme.width#" class="ex12-body">
<html:tr>
<html:td colspan="3" class="ex12-body-top-border">
<br />
</html:td>
</html:tr>
<html:tr>
<html:td width="60" class="ex12-body-gutter">
<br />
</html:td>
<html:td class="ex12-body-content">
#thistag.generatedContent#
</html:td>
<html:td width="60" class="ex12-body-gutter">
<br />
</html:td>
</html:tr>
<html:tr>
<html:td colspan="3" align="center" class="ex12-body-footer">
Questions?
<html:a href="#providers.siteUrl#">I'm here to help.</html:a>
</html:td>
</html:tr>
</html:table>
<ex12:FooterLinks />
<!--- Reset the generated content since we're overriding the output. --->
<cfset thistag.generatedContent = "" />
</cfoutput>
</cfcase>
</cfswitch>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment