これは非常に複雑なものになるため、進行中に追加していきます。
私のアプリは、標準のビューとリージョン (他のビューを含めることのみを目的とした特別なタイプのビュー) の 2 つの主要なビュー タイプから構成されています。 ' 必要に応じて表示します。
アプリのメイン領域 (ヘッダー、フッター、モーダルなど) にあるすべてのビューは、すべて問題なく動作します。今日、他のビュー内にいくつかのサブ領域を作成しようとしましたが、問題が発生しました。何らかの理由でthis.$el.html()
、リージョンに割り当てられたビューの出力を渡すためにリージョンを呼び出すと、何も起こりません。コードをステップ実行すると、ビュー自体が適切にレンダリングされ、コンソールでオブジェクト モデルを見るとマークアップを確認できます。ただし、実際にページに結合されることはなく、リージョン ラッパーを表すマークアップしか表示されません。
ここにいくつかのコードがあります-うまくいけば、ある程度の意味をなすでしょうが、これはかなりの数のレベルに落ちます...
まず、ビューとリージョンの基本クラス...
define(['backbone', 'helpers/cookie-manager'],
function (Backbone, CookieManager) {
var spinner = "<img src='/content/images/global/ajax-loader.png' alt='loading...' />";
var ministryView = Backbone.View.extend({
name: 'Unnamed View',
sectionName: 'No section specified',
stateRequired: false,
template: undefined,
bindings: [],
initialize: function (options) {
this.options = options || {};
Backbone.View.prototype.initialize.call(this, options);
if (this.options.name) {
this.name = this.options.name;
}
if (this.options.sectionName) {
this.sectionName = this.options.sectionName;
}
if (this.options.template) {
this.template = this.options.template;
}
},
bindToModel: function (model, ev, callback, that) {
if (that === undefined || that === null) {
throw "The value of 'that' needs the context of the extending class in order to operate correctly.";
}
model.bind(ev, callback, that);
this.bindings.push({ model: model, ev: ev, callback: callback });
},
dispose: function () {
this.unbindFromAllModels(); // Will unbind all events this view has bound to
this.stopListening();
this.unbind(); // This will unbind all listeners to events from this view. This is probably not necessary because this view will be garbage collected.
this.remove(); // Uses the default Backbone.View.remove() method which removes this.el from the DOM and removes DOM events.
this.undelegateEvents();
},
render: function () {
this.trigger('rendered');
return this;
},
resetStyleState: function(condition) {
},
trash: function () {
this.dispose();
},
unbindFromAllModels: function () {
_.each(this.bindings, function (binding) {
binding.model.unbind(binding.ev, binding.callback);
});
this.bindings = [];
}
});
var ministryRegion = ministryView.extend({
name: 'Unnamed Region',
currentView: undefined,
initialize: function (options) {
this.options = options || {};
ministryView.prototype.initialize.call(this, options);
if (this.options.currentView) {
this.currentView = this.options.currentView;
}
_.bindAll(this, 'placeRenderedView');
_.bindAll(this, 'showRendering');
},
placeRenderedView: function () {
this.$el.html(this.currentView.$el);
this.currentView.delegateEvents();
if (this.currentView.postRender !== undefined && this.currentView.postRender !== null) {
this.currentView.postRender();
}
},
renderView: function (view) {
if (view) {
if (this.currentView) {
this.currentView.trash();
}
this.currentView = view;
}
this.currentView.bind('rendering', this.showRendering);
this.currentView.bind('rendered', this.placeRenderedView);
this.currentView.render();
},
showRendering: function () {
this.$el.html(spinner);
},
trash: function(disposeRegion) {
this.currentView.trash();
if (disposeRegion !== undefined && disposeRegion !== null && disposeRegion !== false) {
this.dispose();
}
}
});
return {
View: ministryView,
Region: ministryRegion
};
});
ビューをロードしたい領域を含むアプリにロードされるビュー ( mealPlansRegion
)...
define(['ministry', 'jquery', 'views/v-header', 'models/m-ns', 'views/components/components', 'text!templates/hub/member-home.html'],
function (Ministry, $, Header, Models, Components, TemplateSource) {
var memberHomeView = Ministry.SecureView.extend({
name: 'Member Home',
sectionName: 'Hub',
mealPlansRegion: undefined,
template: Handlebars.compile(TemplateSource),
headerView: new Header({ text: 'Kitchen Hub', swatch: 'a' }),
initialize: function (options) {
Ministry.SecureView.prototype.initialize.call(this, options);
},
// Need to override the normal secured view implementation.
render: function () {
this.$el.html(this.template(this));
this.mealPlansRegion = new Ministry.Region({ el: '.meal-plans-container' });
this.mealPlansRegion.renderView(new Components.MealPlansList({ collection: new Models.MealPlan.OwnedCollection({ username: App.session.username() }) }));
this.trigger('rendered');
return this;
},
postRender: function () {
if (!this.isSecured()) {
App.router.navigate('/');
App.renderHome(false);
}
}
});
return memberHomeView;
});
...そしてそれはテンプレートです...
<section class="meal-plans-container">
</section>
...現時点では、地域のプレースホルダーのみが含まれています。最終的には、これらのいくつかを交換可能なコンテンツとともにここに置くことを意図しています. 最後に、これが私が読み込もうとしているビューです...
define(['ministry', 'jquery', 'models/m-meal-plan', 'text!templates/components/meal-plans-list.html'],
function(Ministry, $, MealPlan, TemplateSource) {
var mealPlansListView = Ministry.SecureView.extend({
name: 'Meal Plans List Component',
template: Handlebars.compile(TemplateSource),
render: function () {
var that = this;
if (this.isSecured()) {
this.collection.on('fetching', function () {
that.trigger('rendering');
});
this.collection.fetch({
success: function() {
that.bindData();
that.trigger('rendered');
},
error: function(model, xhr) {
that.$el.html('Unable to fetch meal plan data');
if (console !== undefined && console !== null) {
console.log('Fetch Meal Plan failed: ' + xhr.responseText);
}
that.trigger('rendered');
}
});
} else {
this.applySecureLoginPrompt();
}
return this;
},
bindData: function () {
this.$el.html(this.template({ plans: this.collection.toJSON() }));
}
});
return mealPlansListView;
});
そしてテンプレです…
<ul id="mealPlansList" class="swatch-listview-b">
<li class="listview-header">Meal Plans</li>
{{#each plans}}
<li><span class="meal-plan-id-holder hidden">{{id}}</span>{{name}}</li>
{{/each}}
</ul>
この特定のビューでは、共通の地域コードのこの部分が失敗します...
placeRenderedView: function () {
this.$el.html(this.currentView.$el);
this.currentView.delegateEvents();
if (this.currentView.postRender !== undefined && this.currentView.postRender !== null) {
this.currentView.postRender();
}
},
...そして、this.$el.html(this.currentView.$el);
行はまったく何もしません。
他にご不明な点がございましたら、お気軽にお問い合わせください。