backbone.js で同じビューを持つ 2 つのモデルを使用しようとすると問題が発生します。何らかの方法で、トリガーがトリガーされてレンダリング機能が開始される前に、ビューがレンダリングされています。
モデルは次のとおりです。
APP.Models.FamilyPreferences = Backbone.Model.extend({
initialize: function( attributes, options ) {
_.bindAll(this, 'success_handler', 'populate');
this.url = options.url;
},
populate: function(){
this.fetch({success: this.success_handler});
},
success_handler: function(){
this.trigger("change");
}
});
APP.Models.Preferences = Backbone.Model.extend({
initialize: function( attributes, options ) {
_.bindAll(this, 'success_handler', 'error_handler', 'populate');
this.url = options.url;
},
populate: function(){
this.fetch({success: this.success_handler, error:this.error_handler});
},
success_handler: function(){
this.exists = true;
this.trigger("change");
},
error_handler: function(){
this.exists = false;
this.trigger("change");
}
});
ビューからの関連コードは次のとおりです。
APP.Views.PreferencesFormView = Backbone.View.extend({
templates: [{name:"preferences_template", file_path:"preferences_form.html"}],
initialize: function(options){
_.bindAll(this, 'render', 'renderPrereq');
var family_url = "services/family/" + options.family_id;
var preferences_url = "services/preferences/familyID/" + options.family_id;
var ctx = this;
this.alreadyRendered = false;
this.modelsCurrentlyLoaded = [];
this.models = {};
this.models.family = new APP.Models.FamilyPreferences({}, {url: family_url});
this.models.family.on('change', function(){ctx.renderPrereq("family");});
this.models.family.populate();
this.models.preferences = new APP.Models.Preferences({}, {url:preferences_url});
this.models.preferences.on('change', function() {ctx.renderPrereq("preferences");});
this.models.preferences.populate();
},
renderPrereq: function(newmodel){
var inside = ($.inArray(newmodel, this.modelsCurrentlyLoaded)>-1) ? true : false;
if (!(inside)){this.modelsCurrentlyLoaded.push(newmodel);}
var total = Object.keys(this.models).length;
if(this.modelsCurrentlyLoaded.length == total && !this.alreadyRendered){
this.alreadyRendered = true;
this.render();
}
},
render: function(){
var family_data = {
id: this.models.family.attributes.id,
familyGroup: this.models.family.attributes.groupNum,
familyId: this.models.family.attributes.familyId,
probandDob: this.models.family.attributes.childDob,
}
var preferences_data = {
mother: this.models.preferences.attributes[0],
father: this.models.preferences.attributes[1],
exists: this.models.preferences.exists
}
this.$el.html(this.compiledTemplates.preferences_template(family_data));
//bunch of javascript making the page work
}
});
テンプレートは、私の知る限り、正しく機能している別のjs関数を介してロードされています。どういうわけか、レンダリング関数が成功ハンドラーの前に呼び出されています。方法がわかりません。唯一の副作用は、 Preferences モデルが exists プロパティを取得せず、未定義であり、あらゆる種類の問題を引き起こすことです。また、options.family_id が正しく設定されています。どんな助けでも大歓迎です。前もって感謝します。
編集: また、6 回まで renderPrereq を実行するようですが、これもわかりません。
JSON - ファミリ モデル
{
"id": 1,
"familyId": "family01",
"collectionDate": "2013-01-01",
"childDob": "2001-05-06",
"groupNum": "Two",
"probands": [],
"mother": null,
"father": null,
"siblings": []
}
JSON - 設定モデルの最初の部分
[{
"main": "illness-only",
"obesity": "No",
"bloodPressure": "No",
"diabetes": "No",
"heart": "No",
"alzheimers": "No",
"parkinsons": "No",
"mentalHealth": "No",
"breastOvarianCancer": "No",
"prostateTesticularCancer": "No",
"otherCancer": "No",
"childSickleCell": "No",
"childCysticFibrosis": "No",
"childMuscularDystrophy": "No",
"childAutism": "No"
},
{
"main":"more-questions",
"obesity":"No",
"bloodPressure":"Yes",
"diabetes":"No",
"heart":"Unsure",
"alzheimers":"No",
"parkinsons":"Yes",
"mentalHealth":"No",
"breastOvarianCancer":"No",
"prostateTesticularCancer":"No",
"otherCancer":"No",
"childSickleCell":"No",
"childCysticFibrosis":"No",
"childMuscularDystrophy":"No",
"childAutism":"No"}]
ヘッダー
Accept: application / json, text / javascript, /; q=0.01
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Cache-Control:no-cache Connection:keep-alive
Cookie:csrftoken=bDIpdvAPBdWF6dZe9BkpsFSF4wiGl2qX
Host:localhost:8080 Pragma:no-cache Referer:localhost:8080/CSER / index.html
User - Agent: Mozilla / 5.0(Macintosh; Intel Mac OS X 10_8_3) AppleWebKit /
537.36(KHTML, like Gecko) Chrome / 27.0.1453.110 Safari / 537.36 X - Requested - With: XMLHttpRequest
このコードを試してください..
APP.Models.FamilyPreferences = Backbone.Model.extend({
initialize: function (attributes, options) {
_.bindAll(this, 'success_handler', 'populate');
this.url = options.url;
},
populate: function () {
this.fetch();
},
// This is not required
// It will automatically render it as we are listening to the sync event
success_handler: function () {
// Not required
// sync event will take care of it
}
});
APP.Models.Preferences = Backbone.Model.extend({
initialize: function (attributes, options) {
_.bindAll(this, 'success_handler', 'error_handler', 'populate');
this.url = options.url;
},
populate: function () {
this.fetch({
success: this.success_handler,
error: this.error_handler
});
},
success_handler: function () {
this.exists = true;
// Not required
// sync event will take care of it
},
error_handler: function () {
// Do something else
}
});
APP.Views.PreferencesFormView = Backbone.View.extend({
templates: [{
name: "preferences_template",
file_path: "preferences_form.html"
}],
initialize: function (options) {
_.bindAll(this, 'render', 'renderPrereq');
var family_url = "services/family/" + options.family_id;
var preferences_url = "services/preferences/familyID/" + options.family_id;
var ctx = this;
this.alreadyRendered = false;
this.modelsCurrentlyLoaded = [];
this.models = {};
// Family Model
this.models.family = new APP.Models.FamilyPreferences({}, {
url: family_url
});
this.listenTo( this.models.family, 'change', function () {
ctx.renderPrereq("family");
});
// This will take care of rendering it on Sync with server
// No need to triggereing the event explicitly..
this.listenTo( this.models.family, 'sync', function () {
ctx.renderPrereq("family");
});
this.models.family.populate();
// Family Preference Model
this.models.preferences = new APP.Models.Preferences({}, {
url: preferences_url
});
this.listenTo( this.models.preferences, 'change', function () {
ctx.renderPrereq("family");
});
// This will take care of rendering it on Sync with server
// No need to triggereing the event explicitly..
this.listenTo( this.models.preferences, 'sync', function () {
ctx.renderPrereq("preferences");
});
this.models.preferences.populate();
},
renderPrereq: function (newmodel) {
var inside = ($.inArray(newmodel, this.modelsCurrentlyLoaded) > -1) ? true : false;
if (!(inside)) {
this.modelsCurrentlyLoaded.push(newmodel);
}
var total = Object.keys(this.models).length;
if (this.modelsCurrentlyLoaded.length == total && !this.alreadyRendered) {
this.alreadyRendered = true;
this.render();
}
},
render: function () {
var family_data = this.models.family.toJSON());
var preferences_data = {
mother: this.models.preferences.attributes[0],
father: this.models.preferences.attributes[1],
exists: this.models.preferences.get('exists') ? this.models.preferences.get('exists') : false
}
this.$el.html(this.compiledTemplates.preferences_template(family_data);
//bunch of javascript making the page work
}
});