所以我被卡住了。我得到了伟大的脊梁。木偶来处理我嵌套的孩子/父母关系和渲染(用裸主干做这件事是一场噩梦),但是现在我面临着嵌套复合视图的问题,
我总是在找不到指定的itemViewContainer
时收到一个请求:。来自父复合视图-CategoryCollectionView的选项卡内容,虽然itemViewContainer在模板上可用,但我正在尝试做的是,我有一个餐厅菜单需要呈现,因此我有几个类别,在每个类别中我有几个菜单项,因此我的最终html如下所示:
<div id="order-summary">Order Summary Goes here</div>
<div id="categories-content">
<ul class="nav nav-tabs" id="categories-tabs">
<li><a href="#category-1">Appetizers</a></li>
</ul>
<div class="tab-content" >
<div class="tab-pane" id="category-1">
<div class="category-title">...</div>
<div class="category-content">..the category items goes here.</div>
</div>
</div>
以下是我到目前为止的情况:
首先是模板
模板-骨架
<div id="order-summary"></div>
<div id="categories-content"></div>
模板菜单核心
<ul class="nav nav-tabs" id="categories-tabs"></ul>
<div class="tab-content" ></div>
模板类别
<div class="category-title">
<h2><%=name%></h2>
<%=desc%>
</div>
<div class="category-content">
The menu items goes here
<ul class="menu-items"></ul>
</div>
模板菜单项
Item <%= name%>
<strong>Price is <%= price%></strong>
<input type="text" value="<%= quantity %>" />
<a href="javascript:void()" class="add">Add</a>
现在剧本
var ItemModel = Backbone.Model.extend({
defaults: {
name: '',
price: 0,
quantity: 0
}
});
var ItemView = Backbone.Marionette.ItemView.extend({
template: '#template-menuitem',
modelEvents: {
"change": "update_quantity"
},
ui: {
"quantity" : "input"
},
events: {
"click .add": "addtoBasket"
},
addtoBasket: function (e) {
this.model.set({"quantity": this.ui.quantity.val() });
},
update_quantity: function () {
//@todo should we do a re-render here instead or is it too costy
this.ui.quantity.val(this.model.get("quantity"));
}
});
var ItemCollection = Backbone.Collection.extend({
model: ItemModel
});
var CategoryModel = Backbone.Model.extend({
defaults: {
name: ''
}
});
var CategoryView = Backbone.Marionette.CompositeView.extend({
template: '#template-category',
itemViewContainer: ".menu-items",
itemView: ItemView,
className: "tab-pane",
id: function(){
return "category-" + this.model.get("id");
},
initialize: function () {
this.collection = new ItemCollection();
var that = this;
_(this.model.get("menu_items")).each(function (menu_item) {
that.collection.add(new ItemModel({
id: menu_item.id,
name: menu_item.name,
price: menu_item.price,
desc: menu_item.desc
}));
});
}
});
var CategoryCollection = Backbone.Collection.extend({
url: '/api/categories',
model: CategoryModel
});
var CategoryCollectionView = Backbone.Marionette.CompositeView.extend({
el_tabs: '#categories-tabs',
template: '#template-menu-core',
itemViewContainer: ".tab-content", // This is where I'm getting the error
itemView: CategoryView,
onItemAdded: function (itemView) {
alert("halalouya");
//this.$el.append("<li><a href=\"#cateogry-" + tab.get("id") + "\">" + tab.get("name") + "</a></li>");
//$(this.el_tabs).append("<li><a href='#category-" + itemView.model.get("id") + "'>"
//+ itemView.model.get("name") + "</a></li>")
}
});
我知道这有点难理解,但你们是我最后的选择。模板和cateogring获取和其他东西没有问题(它已经在转换从木偶集合到复合视图的类别集合视图之前工作。)
编辑1
根据请求添加了应用程序初始化器:
AllegroWidget = new Backbone.Marionette.Application();
AllegroWidget.addInitializer(function (options) {
// load templates and append them as scripts
inject_template([
{ id: "template-menuitem", path: "/js/templates/ordering-widget-menuitem.html" },
{ id: "template-category", path: "/js/templates/ordering-widget-category.html" },
{ id: "template-menu-core", path: "/js/templates/ordering-widget-menu-core.html" },
{ id: "template-skeleton", path: "/js/templates/ordering-widget-skeleton.html" }
]);
// create app layout using the skeleton
var AppLayout = Backbone.Marionette.Layout.extend({
template: "#template-skeleton",
regions: {
order_summary: "#order-summary",
categories: "#categories-content"
}
});
AllegroWidget.layout = new AppLayout();
var layoutRender = AllegroWidget.layout.render();
jQuery("#allegro-ordering-widget").html(AllegroWidget.layout.el);
// Initialize the collection and views
var _category_collection = new CategoryCollection();
var _cateogories_view = new CategoryCollectionView({ api_key: window.XApiKey, collection: _category_collection });
_category_collection.fetch({
beforeSend: function (xhr) {
xhr.setRequestHeader("X-ApiKey", window.XApiKey);
},
async: false
});
//AllegroWidget.addRegions({
/// mainRegion: "#allegro-ordering-widget"
//});
AllegroWidget.layout.categories.show(_cateogories_view);
});
AllegroWidget.start({api_key: window.XApiKey});
在调用区域上的show之前,您将通过fetch添加到集合中。
木偶。默认情况下,CompositeView在模型添加到其集合时附加ItemViews。这是一个问题,因为itemViewContainer. tab内容没有被添加到dom中,因为该区域没有调用show。
很容易修复,按照下面的方式重新编写代码,应该可以在不重载HTML的情况下工作。
// Initialize the collection and views
var _category_collection = new CategoryCollection();
// grab a promise from fetch, async is okay
var p = _category_collection.fetch({headers: {'X-ApiKey': window.XApiKey});
// setup a callback when fetch is done
p.done(function(data) {
var _cateogories_view = new CategoryCollectionView({ api_key: window.XApiKey, collection: _category_collection });
AllegroWidget.layout.categories.show(_cateogories_view);
});
好的,这很奇怪,但在CategoryCollectionView类中添加此项:
appendHtml: function (collectionView, itemView, index) {
//@todo very weird stuff, assigning '.tab-content' to itemViewContainer should have been enough
collectionView.$(".tab-content").append(itemView.el);
}
解决了这个问题,但是我不知道为什么它的工作原理,分配'. tab内容'到itemViewContainer应该已经足够了,任何想法?