Uncaught ReferenceError: models is not defined in the html file in a backbone.js application

1.9k views Asked by At

demo.js

var CommentsCollection = Backbone.Collection.extend({

    url : "http://0.0.0.0:8080/"

});

var CommentsListView = Backbone.View.extend({

    el: '.page',

    render : function(){
        var that = this;
        var commentsCollection = new CommentsCollection();
        commentsCollection.fetch({
            success: () => {
                    var models = commentsCollection.models;
                    // _.each(models, function(models){
                    //  console.log(models.get('firstname'));
                    // });

                  var template = _.template($('#reddit-comments-template').html());
                  that.$el.html(template(models));
            }
        })
    }
});


var PageRouter = Backbone.Router.extend({
    routes: {
        '' : 'home'
    }
});

Backbone.history.start();

index.html

<html>
<head>
    <title> </title>
</head>
<body>
    <div class="container">
        <h1>Top posts</h1>
        <hr />
        <div class="page"></div>
    </div>

    <script type="text/template" id="reddit-comments-template">
        <table class = "comments table">
            <thead>
                <tr>
                    <th>Row</th>
                    <th>Commments</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <% _.each(models, function(models){ %>
                    <tr>
                        <td><%= models.get('firstname') %></td>
                        <td><%= models.get('lastname') %></td>
                        <td><%= models.get('id') %></td>
                    </tr>
                    <% }); %>
                </tr>
            </tbody>
        </table>
    </script>

    <script type="text/javascript" src="jquery-3.2.1.min.js"></script>
    <script type="text/javascript" src="underscore-min.js"></script>
    <script type="text/javascript" src="backbone-min.js"></script>
    <script type="text/javascript" src="demo.js"></script>

</body>
</html>

Actually if you see, I tried some getting some data from the api and updating the view according to the changes in the data, the collection gets the data from the api and then I get the models of the collection to loop over the data from the model, the variables in the models get printed in the log I added in the js script in the comments as you can see but I guess the value is not passed to the html file, giving rise to that error. Can you please tell me how to correct it.

2

There are 2 answers

0
waranlogesh On BEST ANSWER

You can convert the collection to json and pass it to template and access the models. In this way you can iterate through models using _.each and render their attributes in template.

var CommentsListView = Backbone.View.extend({

    el: '.page',

    render : function(){
        var context = {};
        this.commentsCollection = new CommentsCollection();
        this.commentsCollection.fetch({
            success: () => {
                    //var models = commentsCollection.models;
                    // _.each(models, function(models){
                    //  console.log(models.get('firstname'));
                    // });
                  context['models'] = this.commentsCollection.toJSON()
                  var template = _.template($('#reddit-comments-template').html());
                  that.$el.html(template(context));
            }
        })
    }
});

Template:

<html>
<head>
    <title> </title>
</head>
<body>
    <div class="container">
        <h1>Top posts</h1>
        <hr />
        <div class="page"></div>
    </div>

    <script type="text/template" id="reddit-comments-template">
        <table class = "comments table">
            <thead>
                <tr>
                    <th>Row</th>
                    <th>Commments</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <% _.each(models, function(model){ %>
                    <tr>
                        <td><%= model.firstname %>
                        <td><%= model.lastname %></td>
                        <td><%= model.id %></td>
                    </tr>
                    <% }); %>
                </tr>
            </tbody>
        </table>
    </script>

    <script type="text/javascript" src="jquery-3.2.1.min.js"></script>
    <script type="text/javascript" src="underscore-min.js"></script>
    <script type="text/javascript" src="backbone-min.js"></script>
    <script type="text/javascript" src="demo.js"></script>

</body>
</html>
0
Rajat Badjatya On

Before sending the collection or model to the template first serialize it with toJSON() method that is available on both Backbone's model and collection. When we use toJSON over a collection, it returns an array containing the attributes hash of each model.

var CommentsListView = Backbone.View.extend({
    el: '.page',
    // read and compile the template once
    template: _.template($('#reddit-comments-template').html()),

    render: function() {
        var commentsCollection = new CommentsCollection();
        commentsCollection.fetch({
            context: this, // avoids "that = this;"
            success: function(collection, response, options) {
                that.$el.html(this.template({ models: collection.toJSON() }));
            }
        });
    }
});

PS: I have added the default arguments in success callback.