How to pass additional variables in to underscores templates

13,113

I'm not sure that I fully understand your question. But I do something along these lines to pass multiple objects into my template function.

 $(this.el).html(_.template(html)($.extend({}, this.model.toJSON(), App.lists.toJSON())))

The jquery extend function lets me merge two objects into one. So in your case you could merge your "searchTerm" in with your model during templating.

_.template(html)($.extend({}, row.doc, {"searchTerm": searchTerm}))

Your other option would be to pass your entire model into you template function and perform your underscore iteration in the template. Let me know if you need more explanation on that.

EDIT:

Here is a link to jquery extend

And underscore also has and extend method if you aren't using jquery

EDIT EDIT:

This is just to give you an example of my second suggestion. Would probably need some tweaking to throw into yours, but this is the idea.

template: _.template("

    <% _(rows).each(function(row) { %>
        <tr><td><% print(someKey.replace(searchTerm, '<b>' + searchTerm + '</b>')); %></td></tr>
<% } %>

"),
render: function(){
    this.el.append(this.template(this.model.toJSON()));
}
Share:
13,113
Andreas Köberle
Author by

Andreas Köberle

Updated on June 04, 2022

Comments

  • Andreas Köberle
    Andreas Köberle almost 2 years

    I've a backbone view that renders a search result in a underscore template. As I want to highlight the search term in the result I have the following print method in the template:

    print(someKey.replace(searchTerm, '<b>' + searchTerm + '</b>')
    

    It works as aspected, but I have to set the searchTerm variable in the global namespace to get this work. I wonder if there is a way to access my views model in the print method, so I could write it like this:

    print(someKey.replace(searchTerm, '<b>' + this.model.get('searchTerm') + '</b>')
    

    Or if I could set searchTerm as a local variable in my render function and access it in my template.

    Here is the whole Backbone view:

    var searchTerm;
    var SearchResultView = Backbone.View.extend({
        initialize: function() {
            this.model.bind('change:rows', this.render, this);
            this.model.bind('change:searchTerm', this.clear, this)
        },
        template: _.template("<tr><td><% print(someKey.replace(searchTerm, '<b>' + searchTerm + '</b>')); %></td></tr>", this),
        render: function() {
           searchTerm = this.model.get('searchTerm')
            _.each(this.model.get('rows'), function(row) {
                this.el.append($(this.template(row.doc)));
            }, this)
        },
        clear: function(){
            this.el.empty();
        }
    });
    
  • Andreas Köberle
    Andreas Köberle over 12 years
    It seems a bit overkill to merge a new object in to my result, but after thinking about it, it seems the only solution for the problem, beside using a global variable or to inline the template into the function and declare the searchTerm variable there.
  • Mike
    Mike over 12 years
    I agree that it is a very strange situation. You are basically pulling "searchTerm" off your model, iterating a collection of your model, and then rebinding "searchTerm" to each item in the collection. You could always bind your entire model to the template instead of breaking it apart. Then wrap your html in the _.each() inside your template. It's just preference. Good luck with your project :D