Search code examples
javascripttemplatesbackbone.jsunderscore.jsunderscore.js-templating

How to render a JS object with underscore templates?


I'm trying to render a JS object of data using underscore templates and Backbone.js.

I created data it like below picture.

JS object data

and then, i saw the similar question.
How to display a JS object with underscore templates?

I hadn't known Backbone.js collection and model correctly, but recently I understood those.
I has made data inserting the collection that like below source code.

//that's create view
wordCollection.add(wordList);
var view = new views.Livingword({collection:wordList});

//that's view 
render: function(templateName) {
        var template = _.template(templateName);
        this.$el.html(template({result : this.collection.category}));
        return this;
      }

then, i wrote the html source code.

  <% _.each(result, function(item,key,list){ %>
            <tr>
            <td><%- category[key].bedroom %></td>
            </tr>
          <% }) %>

but, error is printing Uncaught ReferenceError: category is not defined
so i try to debug collection resulting from the console command when i running console.log(this.collection.category); is below picture. this.collection.category result

I think creating data is appropriate and don't find incorrect source code.
How can i render my data in html?


Solution

  • In each of the iterations, item in your code will be values of stuff like "bedroom", which are arrays containing objects.
    So in order to go through and print each items inside it, you need another iteration.

    <% _.each(result, function(arr, key, list){ %>
     <!-- Add <tbody>, <thead> etc with "key" here -->
    
      <% _.each(arr, function(item, key, list){ %>
         <tr>
            <td><%= item.audioSrc %></td>
         </tr>
      <% }) %>
    
    <% }) %>
    

    Now in the above code, audioSrc is hardcoded. If you know all the properties you want to print, you can do that. If you don't (they are dynamic), then you need another iteration to go through each properties of item.

    Side notes:

    • Instead of executing var template = _.template(templateName); on every render, do

      template: _.template(templateName), // one time
      render: function(templateName) { 
          this.$el.html(this.template({result: this.collection.category}));
          return this;
      }
      
    • Give meaningful names to things you pass into template. result is a vague name. category is better, but it being a map of categories, proper naming would be categories. So this.template({categories: this.collection.category}. If the names are clear you'd have a better idea of what you're doing while writing the template

    • Based on the usage: this.collection.category, I'm pretty sure it should be a model and not collection. Collection is for group of things and you'd be using it's models array like this.collection.models.
      So with all the changes your code should be something like

      template: _.template(templateName), // one time
      render: function(templateName) { 
          this.$el.html(this.template({categories: this.model.categories});
          // ---- This can be an Array or Collection instance -----^
          return this;
      }
      

      With template:

      <% _.each(categories, function(category, name){ %>
      <!-- Add <tbody>, <thead> etc with "name" here -->
      
        <% _.each(category, function(item, name){ %>
          <tr>
            <td><%= item.audioSrc %></td>
          </tr>
        <% }) %>
      
      <% }) %>