1
votes

I've come across this backbone / underscore template binding issue that I can't get my head around.

The underscore template is being provided a collection of objects however when traversing the collection and building the resultant HTML not all the individual object attributes are being resolved.

  1. I believe the template is receiving the collection correctly (asynchronous call to the server). I've debugged the received collection and its populated correctly.
  2. I've "rendered" the raw collection items within the HTML to verify I'm dealing with the correct objects...all appears correct.

I've simplified the code here in the hopes of not blurring the issue. A click event is responsible for selecting a section(not included in code)

Here is the code:

//Underscore Template 
<script id="articles-template2" type="text/html">
<table>
    <thead>
        <tr>
            <th>Title</th>
            <th>Description</th>
            <th>Date</th>
            <th>Data</th>
        </tr>
    </thead>
    <tbody>
    <% _.each(articles, function(a){ %>
        <tr>
            <td><%= JSON.stringify(a)%></td>
            <td><a href="#" data-id="<%= a.id%>"><%= a.title %></a></td>
            <td><%= a.description%></td>
            <td><%= new Date(a.date)%></td>
        </tr>
    <%});%>
    </tbody>
</table>
</script>
// Backbone View ----------------
window.ArticlesView2 = Backbone.View.extend({
    initialize: function () {
        var self = this;
        self.collection.on("reset", this.render, this);
    },
    template: _.template($('#articles-template2').html()),
    render: function () {
        var self = this;
        $(self.el).html(self.template({ articles: self.collection.models }));
        $('#section-list').append(self.el);
        return self;
    },
    events: {
        "click a": "clicked"
    },
    clicked: function (e) {
        var self = this;
        e.preventDefault();
        var id = $(e.currentTarget).data("id");
        var item = self.collection.get(id);
        var name = item.get("title");
        alert(name);
    }
});
// Router ----------------
var AppRouter = Backbone.Router.extend(
          {
              routes: {
                   'section/:title': 'viewSection'
              },
              viewSection:function(section)
              {
                  var self = this;
                  self.articles = new ArticleList({ selectedSection: section });
                  self.view = new ArticlesView2({ collection: self.articles });
                  self.articles.fetch({ reset: true });
              }
          }
);  
// Initialize ----------------
var app = new AppRouter();
Backbone.history.start();
app.navigate('section/Home', { trigger: true });

The rendered HTML is as follows :

<table>
    <thead>
        <tr>
            <th>Title</th>
            <th>Description</th>
            <th>Date</th>
            <th>Data</th>
        </tr>
    </thead>
    <tbody>
         <tr>
            <td>{"id":"527c61082241f813c09c7041","title":"title here","description":" test descript here","date":"2005-02-08T05:00:00.0000000Z"}</td>
            <td><a href="#" data-id="527c61082241f813c09c7041"></a></td>
            <td></td>
            <td>Invalid Date</td>
        </tr>
     </tbody>
</table>

I'm not sure why one can Stringfy() the object and get data but fail to interrogate its attributes successfully????? Is this a event issue, man what am I missing? Thanks

1

1 Answers

1
votes

You're passing the raw array of your models to your template and a model is not a hash, you don't have direct access to the properties.

Either use collection.toJSON

self.template({ articles: self.collection.toJSON() })

or use model.get in your template

<%= a.get('title') %>

Note that in your example JSON.stringify will give you the expected representation of your data because

toJSON behavior

If an object being stringified has a property named toJSON whose value is a function, then the toJSON method customizes JSON stringification behavior: instead of the object being serialized, the value returned by the toJSON method when called will be serialized.

and your models have a toJSON method.