Handling “variable is not defined” with underscore template engine

One of the cool thing with backbone.js is that you can plug in about any javascript templating engine there is. Also another nice extra is that there is one already bundled with underscore.js that is quite powerful.

Personally the template engine provided with underscore cover most of my use cases and is enough for me, but there is one thing that I have found very unpleasant, you cannot pass undefined keys to it. Here an example:

var template =_.template($("#titlebar_tpl").html());
var data = {"title":"Planning"};
<script id="titlebar_tpl" type="text/template">
<input id="<%= id %>">
<span class="title"><%= title %></span>

There you go, in this example id will be undefined and will throw a js error, that is quite an hassle when you handle dynamic templates that might not always have all the data asked in the template.

Fortunately, there is an easy fix

While direct properties will throw an error, wrapping this in another object will do the trick. Here an example:

// Old way
var data = {"title":"Planning"};
// New way
var data = {"data": {"title":"Planning"}};
<script id="titlebar_tpl" type="text/template">
<input id="<%= data.id %>">
<span class="title"><%= data.title %></span>

Slightly painful code wise, but still a nice solution without headache. Another nice touch, you do not even have to check if the property exist, it will not show as undefined but just not show at all (You can of course check if it exists to add code logic in your template).

There you go!

Cedric Dugas is an experienced front-end developer and founder of Position: Absolute, based in Montreal, Canada. When he is not doing CSS and jquery (does it ever happen?), he likes to read on web usability and play trumpet. Why don't you follow him on twitter.

7 Comments on "Handling “variable is not defined” with underscore template engine"

  1. It's even easier as the template function internally uses obj so you could write obj.id

  2. Ondra says:

    But this might change in the future …

  3. Igor says:

    Any ideas why this might happen? Maybe it’s because it’s evaled?
    As I can see using the template source, if you process a template with the following construct:


    The if construct turns into a simple “if (id)”. This has to work with undefined variables, or am I missing something?

  4. Nathan says:

    Nice. I was looking for this solution (great that this was the first page I read).

    Even better, I realise that this enables us to do simple namespacing in our templates, which was something that I just realised I needed 5 mins before reading your article, but didn’t know how I was going to cleanly get around it.

    Now I do! Thanks! :)

  5. Eka says:

    I have also tried _.isUndefined(title), but it doesn’t work either.
    but your solution just work.
    Thank you

  6. Ben says:

    I’ve found a couple things to be helpful. What you outlined above is really good, especially if you expand on it a bit: { data: model.toJson(), permissions: somePermObject, state: someStateObject }. State and permissions can be useful bits of data for a view that can be kept out of the model.

    Also, in a less pleasant way, you can check a variable like this:

    {{ if(null != someVar) { }}
    // do stuff
    {{ } //end if }}

    null != will work without crashing an underscore template.

Got something to say? Go for it!