Skip to content

Instantly share code, notes, and snippets.

@Pointy
Created September 12, 2012 15:22
Show Gist options
  • Save Pointy/3707350 to your computer and use it in GitHub Desktop.
Save Pointy/3707350 to your computer and use it in GitHub Desktop.
An approach with doT templates to handling the "option"/"radio" coding mess
<!--
This is the template source for the page containing a "select". In doT
templates the data object is by convention called "it" (though it can
be set to be anything). In this example, I'm inventing a field called
"choice", whose value would presumably have come from the server via
JSON (or whatever) as the property "choice" of the "it" parameter.
In the option elements you'll see the doT construct to fetch a value
from the "it" object, and you'll see that it involves what looks like
a function call. It *is* a function call, a call to another doT template
that is really the point of this. That's in a separate file.
-->
<form id='...' method=post action='...'>
<select name=choice>
<option {{= $T.optionVal("value1", it.choice) }}>The First Choice
<option {{= $T.optionVal("value2", it.choice) }}>The Second Choice
<option {{= $T.optionVal("value3", it.choice) }}>The Third Choice
</select>
<!--
Handling the list of options case
Assume that our "it" object looks like this:
{
"settings" : {
"foo" : "low",
"bar" : "high",
"baz" : "low"
}
}
and we want a labeled set of radio button pairs.
I'll assume a sub-template, "$T.radioVal", that's
like the "optionVal" template only for radio buttons
("checked" instead of "selected" basically). Because
the "settings" value is an object and not an array (which,
if I had control of the server's JSON, I wouldn't do)
I'll need a function to transform that into an array,
which is of course a trivial utility.
-->
{{~ $T.toArray(it.settings) :setting }}
<h2>{{! setting.name }}</h2>
{{~ ["low", "high"] :lowHigh }}
<input type=radio name={{! setting.name }} {{= $T.radioVal(setting.value, lowHigh) }}> {{= lowHigh }}
{{~}}
{{~}}
<!--
This is my doT "optionVal" template. I compile my templates server-side
as part of my Ant-based application build (it's a Java application).
The build includes a home-grown Ant task that extracts templates from
the source and runs them through doT.js via Rhino. The templates are
then combined into a single JavaScript source file as properties of
an eventually global object called $T (my company is called "Tango" :-)
so references to templates is always via that symbol.
This simple template exploits the ability to override the default doT
template signature. I'll show what my code actually looks like; the
little header line is interpreted by the above-mentioned Ant task in
a way that should be obvious.
This template is extremely simple, and an invocation of it is not
much less typing than the code would be, but it's purpose is more to
reduce the chances for a typo in templates that call it.
-->
<%-- template optionVal(value, actual) --%>
value={{! value }} {{= value == actual ? "selected" : "" }}
<!-- The "toArray" function (as a template, though it wouldn't have to be this way -->
<%-- template toArray(obj) --%>
{{
var key, rv = [];
for (key in obj)
if (obj.hasOwnProperty(key))
rv.push({name: key, value: obj[key]});
return rv;
}}
@getify
Copy link

getify commented Sep 12, 2012

the difficulty, at least for a lot of templating engines, is that there's some namespace scope collision difficulty with two nested loops, when inside the inner loop you need to reference the key/iterator from the outer loop.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment