骨干听定制收藏?

时间:2014-11-07 21:39:53

标签: javascript backbone.js marionette

// build a collection of players with this team ID
this.collection = new PlayersCollection(App.data.players.where({team_id: this.model.id}));

当我这样做时,它呈现this.collection = App.data.players;它与集合作为​​新集合有关,我该如何收听新集合?

使用牵线木偶,我将一系列玩家传递给一组具有collectionViews,compositeViews和itemViews的团队。

团队collectionView> Team compositeView>播放器itemView

在团队复合视图中,我将this.collection定义为与特定团队ID匹配的新PlayersCollection。这呈现完美,但添加一个新的播放器我无法重新渲染视图而无需刷新页面。

addPlayer: function(e) {
    e.preventDefault();

    var $newPlayer = this.$el.find('input.player_name');

    var Player = {
        player_name : $newPlayer.val(), 
        team_id     : this.model.id
    }

    App.data.players.create(Player);
    $newPlayer.val('');

},

以下是大部分代码。我正在尝试添加/创建一个新的播放器并使用listenTo更新视图,但由于这不是定义集合的传统方式,我似乎必须找到一种方法来绑定它?

Teams.js

var Marionette = require('backbone.marionette'),
    playerView = require('./player'),
    PlayersCollection = require('../../collections/players');

var teamView = Marionette.CompositeView.extend({
    events: {
        'submit #AddPlayer': 'addPlayer'
    },
    initialize: function() {
        // anytime something within this specific team changes, render
        this.listenTo(this.model, 'change', this.render);

        // build a collection of players with this team ID
        this.collection = new PlayersCollection(App.data.players.where({team_id: this.model.id}));

    },
    addPlayer: function(e) {
        e.preventDefault();

        var $newPlayer = this.$el.find('input.player_name');

        var Player = {
            player_name : $newPlayer.val(), 
            team_id     : this.model.id
        }

        App.data.players.create(Player);
        $newPlayer.val('');

    },
    itemView: playerView,
    appendHtml: function(collectionView, itemView){
        collectionView.$('.the-players').append(itemView.el);
    }
});

module.exports = CollectionView = Marionette.CollectionView.extend({
    initialize: function() {
        this.listenTo(this.collection, 'change', this.render);
    },
    itemView: teamView
});

Players.js

var Marionette = require('backbone.marionette');

module.exports = playerView = Marionette.ItemView.extend({
    className: 'players-wrap row',
    template: require('../../../templates/teams/player.hbs'),
    events: {
        'mouseenter .player-image': 'playerOn',
        'mouseleave .player-image': 'playerOff',
        'click .player-image': 'playerClicked',
        'keydown': 'on_keypress',
        'click .one-point': 'onePoint',
        'click .two-point': 'twoPoint',
        'click .three-point': 'threePoint'
    },
    initialize:function() {
        _.bindAll(this, 'on_keypress');
        $(document).bind('keydown', this.on_keypress);
        this.listenTo(this.model, 'change', this.render);
        this.$el.attr('data-player', this.model.get('player_name').replace(/\s+/g,"_").toLowerCase());
        window.play = this.model;
    },
    playerOn:function(e) {
        this.$el.addClass('hover');
        this.findPlayer(this.model.get('player_name'), 'add');      
    },
    playerOff:function() {
        this.$el.removeClass('hover');
        this.findPlayer(this.model.get('player_name'), 'remove');
    },
    playerClicked:function() {
        this.$el.toggleClass('hover-clicked');
        this.findPlayer(this.model.get('player_name'), 'toggle'); 
    },
    findPlayer:function(name, action) {
        var player = $('.data-wrap .player-data[data-player='+ name.replace(/\s+/g,"_").toLowerCase() +']');
        if(action === 'toggle') { player.toggleClass('show-confirmed-clicked') }
        if(action === 'add')    { player.addClass('show-player-data') }
        if(action === 'remove') { player.removeClass('show-player-data') }
    },
    onePoint:function(e) {
        var addStat = parseInt(this.model.get('points')) + 1;        
        this.model.set('points', addStat);
        this.model.save();
    },
    twoPoint:function(e) {
        var addStat = parseInt(this.model.get('points')) + 2;        
        this.model.set('points', addStat);
        this.model.save();
    },
    threePoint:function(e) {
        var addStat = parseInt(this.model.get('points')) + 3;        
        this.model.set('points', addStat);
        this.model.save();
    },
    on_keypress:function(e) {
        this.keyStat(e, 49, 'points', 1);   // 1 point
        this.keyStat(e, 50, 'points', 2);   // 2 points
        this.keyStat(e, 51, 'points', 3);   // 3 points
        this.keyStat(e, 82, 'rebounds', 1); // R rebounds
        this.keyStat(e, 83, 'steals', 1); // S steals
    },
    keyStat:function(e, keyVal, stat, number) {
        if(e.keyCode == keyVal && !e.ctrlKey) { 
            if(this.$el.hasClass('hover')) {
                var addStat = parseInt(this.model.get(stat)) + number;        
                this.model.set(stat, addStat);
                this.model.save();
            }
        }
    },
    templateHelpers:function(){
        return {
            name_format: this.model.get('player_name').replace(/\s+/g, '_').toLowerCase()
        }
    }
});

1 个答案:

答案 0 :(得分:1)

我无法找到将新模型添加到CompositeView的集合中的位置?我发现只有App.data.players.create(Player);不是CompositeView的集合。

如果App.data.players是另一个需要与远程服务器保持同步的Backbone.Collection,并且因此您使用create将其持久保存到服务器,则更改addPlayer,如下所示:

addPlayer: function(e) {
    e.preventDefault();

    var $newPlayer = this.$('input.player_name');

    var Player = {
        player_name : $newPlayer.val(), 
        team_id     : this.model.id
    }

    var newPlayer = App.data.players.create(Player);
    this.collection.add(newPlayer);
    $newPlayer.val('');

}, 

CompositeView会抓住"添加"收集事件并将附加新的itemView。 如果有帮助,请尝试告诉我。

只是注意事项:在审核了您的代码后,我发现Teams.js中的appendHtml可以使用itemViewContainer属性删除,其值为.the-players将提高渲染性能。