Search code examples
javascriptinternet-explorerunderscore.jstemplate-engineunderscore.js-templating

Underscore.js template IE9 / IE10 not returning right code


I have this code in my js file

var selectedTagElement = _.template('$("#selected_tag_item_template").html()', item = { tag: label, value: value });
$('#wrapper_id').append(selectedTagElement); 

and this in my html file

    <script type="text/template" id="selected_tag_item_template">
      <div class="tag_item selected js-selected_tag_item" 
           data-tag-value="<%= item.value %>" 
           data-tag-label="<%= item.tag %>"><%= item.tag %>
      </div>
    </script>

Everything is working fine in all browser but IE9 and IE10. If it try

console.log(selectedTagElement)

all i get is

LOG: function(n){return o.call(this,n,m)} 

and if i try to print the item variables in my html file, like this

<%= item %>

i get this

function item() { [native code] }

What's going wrong? Thanks


Solution

  • The output you're getting from:

    console.log(selectedTagElement)
    

    indicates that selectedTagElement is a function. You used to be able to compile and fill in a template in one step but that stopped working in Underscore 1.7.

    You need to start building your selectedTagElement in two steps:

    1. Compile the template to a function using _.template.
    2. Run that function with the desired data to get your HTML.

    So you want to be saying this:

    var t = _.template($('#selected_tag_item_template').html());
    var selectedTagElement = t({ item: { tag: label, value: value } });
    

    That should work everywhere and matches the standard usage.


    Your code works by accident where it works at all. I'm going to assume that '$("#js_template").html()' is just a typo because it doesn't make sense otherwise. Let us break up your code into something equivalent:

    item = { tag: label, value: value };
    var selectedTagElement = _.template('$("#js_template").html()', item);
    $('#wrapper_id').append(selectedTagElement); 
    

    The first line creates a global item variable that holds the data you want to give to the template.

    The second line will compile the template into a function and ignore the second item argument completely since it doesn't match any of _.template's options.

    The third line hands a function to [append]2. Normally you give append a string of HTML or a DOM node but you can also give it a function; when you give append a function, it runs the function and uses its return value as an HTML string. In non-IE browsers, the template function will get the item through your accidental global variable:

    item = { tag: label, value: value }
    

    but IE is using an item function (which is implemented with native code in the browser) from somewhere instead of using your item variable.