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 a front-end veteran with more than 9 years under the belt, between his open source projects & entrepreneurial ambitions he is a product architect at CakeMail. Why don't you follow him on twitter.

20 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. avatar Ondra says:

    But this might change in the future …

  3. avatar 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. avatar 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. avatar Eka says:

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

  6. avatar 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.

  7. avatar micrddrgn says:

    Or you can just set

    _.templateSettings.variable = ‘data’;

    and all your data will available through “data.variable” not only in this but in all templates

  8. avatar Joe says:

    Not necessary guys, check the underscore source code, the “obj” is already there, just write like this and you will be golden.

    <input id="”>

  9. avatar Allen says:

    If i my json obj has 10 fields, i have chosen 3 fields(which may differ each time depends upon the user selection) and i wanna render it as a table, how am i supposed to give . any idea???

  10. avatar alex says:

    Brilliant!!! Thank you.

  11. avatar Swarnendu De says:

    Why not use this?

  12. avatar Geo says:

    Thank you so much! This really improved my quality of life.

  13. What’s up to every single one, it’s really a good
    for me to go to see this website, it consists of priceless Information.

    Here is my webpage: locked file folders on iphone

  14. Normally I do not learn post on blogs, however I would like to
    say that this write-up very compelled me to try and do
    it! Your writing style has been amazed me. Thanks, quite nice

    My weblog … youtube to mp3 android apps

  15. avatar Alexander says:

    you don’t need quotes for your JSON

    var x = {“name”:”frenchie”};

    just do this

    var x = {name:”frenchie”}

    it’s just hurts my head to see quotes when they aren’t necessary. so much more readable without the quotes too.