简体   繁体   中英

Backbone and underscore - templating a simple view

I'm not having much luck with my first templated view in Backbone and underscore.

I get a 'players is not defined error' from Underscore library.

This is my Model:

define([
    'domLib',
    'underscore',
    'backbone',
    'router'
    ],
    function($, _, Backbone, Router) {

        var PlayerModel = Backbone.Model.extend({
            defaults: {
                username: '',
                rank: 0,
                score: 0
            }
        });

        return PlayerModel;

});

This is my collection:

define([
    'domLib',
    'underscore',
    'backbone',
    'router',
    'model/player'
    ],
    function($, _, Backbone, Router, PlayerModel) {

        var LeaderboardCollection = Backbone.Collection.extend({
            model: PlayerModel,
            url: '/hyc-web/leaderBoard/topOverall?count=5'
        });

        return LeaderboardCollection;
});

The associated view:

define([
    'domLib',
    'underscore',
    'backbone',
    'router',
    'collection/leaderboard',
    'text!template/leaderboard.html'
    ],
    function($, _, Backbone, Router, LeaderboardCollection, LeaderboardTemplate) {

        var LeaderboardView = Backbone.View.extend({
            el: '#leaderboard',
            template: _.template(LeaderboardTemplate),
            initialize: function(){
                this.collection = new LeaderboardCollection();              
                this.collection.on('reset', this.render, this); 
                this.collection.fetch();                                        
            },
            render: function(){         
                console.log(this.collection.models);
                this.$el.html(this.template, {players: this.collection.models});
            }
        });

        return LeaderboardView;
});

And the template itself:

<table class="table table-bordered">
    <thead>                             
        <tr>
            <td>Rank</td>
            <td>Player</td>
            <td>Score</td>
        </tr>
    </thead>
    <tfoot>
        <!-- Logged in user details here -->
    </tfoot>
    <tbody>
        <% _.each(players, function(player){ %>
            <tr>
                <td><%= player.rank %></td>
                <td><%= player.username %></td>
                <td><%= player.highScore %></td>
            </tr>           
        <% }); %>                                   
    </tbody>
</table>

It was all going so well until i tried wiring up to the actual data service layer. I cannot see why this is not templating the JSON array?

You probably want your render method to look more like:

render: function() {
  this.$el.html(this.template({ players: this.collection.toJSON() });
}

You need to pass the data context through your view's template() function, not the jQuery html() function. Also, you want to convert the collection to JSON using collection.toJSON() instead of passing in a raw array of models using collection.models.

After some digging around in the docs i came up with this:

define([
    'domLib',
    'underscore',
    'backbone',
    'router',
    'collection/leaderboard',
    'text!template/leaderboard.html'
    ],
    function($, _, Backbone, Router, LeaderboardCollection, LeaderboardTemplate) {

        var LeaderboardView = Backbone.View.extend({
            el: '#leaderboard',
            template: _.template(LeaderboardTemplate),
            initialize: function(){
                var self = this;
                self.collection = new LeaderboardCollection();
                self.collection.fetch({
                    success: function(collection, response, options){
                        self.$el.html(self.template({ players: collection.toJSON()}));
                    }
                })              

            }
        });

        return LeaderboardView;
});

Which renders correctly. As the fetch call is asynchronous i assume that calling the template render after the fetch does not account for the data actually being there. Further research suggests that this is not the way to populate a view on page load but to bootstrap it instead

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM