vandr0iy
vandr0iy

Reputation: 3

Underscore.js - template does not compile on first time

I am trying to render a template with underscore.js from the function triggered when an ajax call (which provides me the JSON I need) succeeds.

I'm experiencing some kind of strange behaviour:

Uncaught ReferenceError: response is not defined

My JSON has this structure:

{
    data: [ 
        item1: {count: "1", url: "http://example1.com", id:"arstd", formatted:"1"},
        item2: {count: "53", url: "http://example2.net", id:"hneio", formatted:"0"},
        ...
    ]
}

My underscore.js template:

<script type="text/template" id="count_template">
    <% _.each (response.data, function (item) { %>
    <a href="<%- item.url %>">
        <li>
            <p id="<%- item.id %>" class="name">
                <%- item.formatted %>
            </p>
            <p id="<%- item.id %>_count" class="count">
                <%- item.count %>
            </p>
        </li>
    </a>
    <% }); %>
</script>

My ajax callback function:

var on_result_count_fetched = (function () {
    var totals = $(".regions .count");
    var ajax_loader = $("#ajax_loader");
    var c_tl = $('#count_template');
    var count_div = $('#res_count');
    //getting the template for the count response
    if (c_tl) {
        var c_template = _.template(c_tl.html());
    }
    _.templateSettings.variable = "response";
    //real callback
    return function (response) {
        if (response.redirect) {
            window.location.replace(data.redirect);
        } else {
            //hide loading animation
            ajax_loader.hide();
            if (!response && _.isEmpty(response)) {
                var tmp = $("<button>In case of fail: do this other action!</button>")
                tmp.click (function() {
                    fetch_results ("searx");
                });
            } else {
                console.log(response);
                var tmp = c_template(response);
            }
            count_div.empty();
            count_div.append(tmp);
        }
    }
}());

Upvotes: 0

Views: 146

Answers (1)

mu is too short
mu is too short

Reputation: 434945

When you say _.template(some_string), Underscore will use the values from _.templateSettings to parse some_string and convert it to a JavaScript function. Once _.template has returned a compiled template function to you, the contents of _.templateSettings no longer matter.

You're doing this sort of thing:

var t = _.template(some_string);
_.templateSettings.variable = "response";

so your _.templateSettings.variable assignment comes too late to affect your _.template call. You need to adjust _.templateSettings before calling _.template so this:

if (c_tl) {
    var c_template = _.template(c_tl.html());
}
_.templateSettings.variable = "response";

should look more like:

if (c_tl) {
    _.templateSettings.variable = "response";
    var c_template = _.template(c_tl.html());
}

Or you could skip _.templateSettings altogether and say:

var tmp = c_template({ response: response });

when calling the template function. Messing around with _.templateSettings can have side effects if your other templates aren't expecting to have to use response to access their data. Configuring _.templateSettings globally in exactly one place or leaving it alone completely tend to work better.

Upvotes: 0

Related Questions