Марионетка CompositeView. Представление для каждой ячейки в таблице
Я хочу сделать таблицу, используя марионетку, чтобы создать игру жизни. Все примеры, которые я нашел, создают CompositeView и имеют itemView, который представляет строку. Это не так уж и здорово, потому что если какая-либо ячейка изменится, тогда весь ряд будет отображен снова.
Было бы здорово, если бы у вас было так, чтобы:
CompositeView (для таблицы и тела таблицы) имеет коллекцию коллекций строк имеет CollectionView (который представляет строку) имеет коллекцию ячеек, которые отображаются с помощью ItemView
Обновление В настоящее время код распечатывает ожидаемое объявление в виде сетки, но поскольку Game.RowView назначает коллекцию в инициализаторе, он, похоже, не прослушивает события, когда модель в коллекции изменяется, и, следовательно, представление моделей не отображается. не перерисовывается.
Чтобы увидеть код, просмотрите этот jsfiddle, который инкапсулирует проблему http://jsfiddle.net/LPg2x/12/ Обновлено
обновленный
<div id="gameRegion"></div>
<script id="gridTemplate" type="template-x-handlebars">
<tbody></tbody>
</script>
обновленный
var GameOfLife = new Backbone.Marionette.Application();
GameOfLife.addRegions({
gameRegion: "#gameRegion"
});
// Create a var for the module where everything lives
var Game = GameOfLife.module("Game");
// The controller that will create all of the cells and the GridView. Showing it in the gameRegion
Game.Controller = Backbone.Marionette.Controller.extend({
initialize: function (options) {
var rowArray = [];
for (var rowCounter = 0; rowCounter < options.rows; rowCounter++) {
var cellArray = [];
for (var columnCounter = 0; columnCounter < options.columns; columnCounter++) {
cellArray.push(new Game.Cell());
}
rowArray.push(new Game.Row({
cellCollection: new Game.CellCollection(cellArray)
}));
}
var gridView = new Game.GridView({
collection: new Game.RowCollection(rowArray)
});
GameOfLife.gameRegion.show(gridView);
}
});
// Model for a cell that starts off being alive
Game.Cell = Backbone.Model.extend({
defaults: {
state: "ALIVE"
},
toggleState: function(){
if(this.get("state") === "ALIVE"){
this.set("state", "DEAD");
}
else{
this.set("state", "ALIVE");
}
console.log("Toggle state on model " + this.cid);
}
});
Game.CellCollection = Backbone.Collection.extend({
model: Game.Cell
});
Game.Row = Backbone.Model.extend();
Game.RowCollection = Backbone.Collection.extend({
model: Game.Row
});
// View for a cell. Its just a td and the template will render the models state
Game.CellView = Backbone.Marionette.ItemView.extend({
template: function(){
return "";
},
className: function(){
return this.model.get("state") === "ALIVE" ? "alive" : "dead";
},
tagName: "td",
events: {
"click" : "toggleState"
},
toggleState: function(){
this.model.toggleState();
}
});
// CollectionView for a row. Its just a tr, which will have all its cells/tds rendered into it
Game.RowView = Backbone.Marionette.CollectionView.extend({
tagName: "tr",
itemView: Game.CellView,
initialize: function(){
this.collection = this.model.get("cellCollection");
}
});
// CompositeView for the table. The template create the structure and we render the rows into the tbody
Game.GridView = Backbone.Marionette.CompositeView.extend({
template: Handlebars.compile($("#gridTemplate").html()),
tagName: "table",
itemView: Game.RowView,
itemViewContainer: "tbody"
});
// Create a new controller instance when the game module is loaded with the application
Game.addInitializer(function (options) {
var controller = new Game.Controller(options);
});
// Start the game with a 10x10 grid
GameOfLife.start({
rows: 10,
columns: 10
});