Thomas
Thomas

Reputation: 5089

Underscore Conditionals in Template

Here is my template:

var tmpl = _.template('<<%= elementTag %> <% if (_.has(elementClass)) { %> class="<%= elementClass %>" <% } %> <%= elementExtra %>><%= template(elementContent) %></<%= elementTag %>>');

Some of the objects that I will render using this template my not have an elementClass attribute set. I've tried to use _.has so that the template only attempts to print the attribute for objects where elementClass is defined but I have had no success. The console error states only that elementClass is not set, presumably because the conditional statement failed to work as I had intended.

I know this is a simple problem, but I can't seem to solve it - how can I use conditionals in statements like this to detect objects without certain attributes set?

Upvotes: 1

Views: 2457

Answers (2)

mu is too short
mu is too short

Reputation: 434665

You can't, in general, use _.isDefined for this. Consider this template:

<script id="t" type="text/x-underscore-template">
    <% if(!_.isUndefined(elementClass)) { %>
        <%= elementClass %>
    <% } else { %>
        No such thing.
    <% } %>
</script>

and this code:

var t = _.template($('#t').html());
console.log(t({ }));

The call to t should give you a ReferenceError because there is no elementClass in scope for the compiled template function. So, if your objects don't have an elementClass property at all, then the template function will fail when you try to get your template.

Demo: http://jsfiddle.net/ambiguous/H22D2/

The problem is that the _.isUndefined function can only check the value of an expression, it cannot check if the variable (or property due to the template's internal with usage) you're passing to it has been declared.

If the objects will have an elementClass property but it might have an undefined value then you can use _.isDefined and this:

t({ elementClass: undefined })

would be fine.

Demo: http://jsfiddle.net/ambiguous/LUakg/

If the objects might or might not have elementClass properties, then you're stuck using typeof as typeof doesn't try to evaluate its operand. Something like this:

<script id="t" type="text/x-underscore-template">
    <% if(typeof elementClass !== 'undefined') { %>
        <%= elementClass %>
    <% } else { %>
        No such thing.
    <% } %>
</script>

will work fine in all three cases of interest:

var t = _.template($('#t').html());
console.log(t({ }));
console.log(t({ elementClass: undefined }));
console.log(t({ elementClass: 'pancakes' }));

Demo: http://jsfiddle.net/ambiguous/H5xC7/

Upvotes: 4

ericponto
ericponto

Reputation: 736

You can check if the elementClass is not undefined. (Using _.isUndefined, as I previously thought would work, doesn't.)

var tmpl = _.template('<<%= elementTag %> <% if ( typeof elementClass !== "undefined" ) ) { print("class=\'elementClass\'") } %> <%= elementExtra %>><%= template(elementContent) %></<%= elementTag %>>');

Upvotes: 1

Related Questions