こんにちは、ember アプリで 2 つの異なる問題が発生しています。どちらもバインディングに関係しています。
まず、したくないときにバインディングを起動します。基本的に私が達成しようとしているのは (私は調査作成者のフロントエンド アプリを構築しています)、質問の「名前」フィールドにテキストが入力されたときに、レンダリングする新しい質問オブジェクトを追加したいということです。ユーザーが追加している質問のリストの最後に別の空白の質問を追加します。これには常に新しい質問があるという効果があるため、質問の追加ボタンは必要ありません。バインディングは機能しており、新しいオブジェクトが追加されています。ただし、バインディングは最新の質問オブジェクトからのものであるため、新しいオブジェクトが作成されるとバインディングが再びトリガーされ、新しいオブジェクトが作成され、バインディングが再びトリガーされます。 ....明らかに最終的にブラウザがクラッシュします。Ember._suspendObserver 関数を使用してみましたが、ありません。これに関する多くのドキュメントがありますが、私はそれを間違って使用していると思います-とにかく、オブザーバーを一時停止したり、バインディングを一時停止したりしていません. コード内のオブザーバーは 27 行目あたり (contentsNameObserver) です。
私が抱えているもう1つの問題-ユーザーが希望する質問のタイプ(単一回答、複数選択など)を選択する選択ドロップダウンボックスがありますが、選択ボックスと{{#each}の間のバインディング種類の質問をレンダリングするヘルパーがトリガーされません。私は Ember.Select ビュー ヘルパーを使用しているので、get/set を使用してバインディングを起動しても問題はありません。計算されたプロパティを使用して、質問タイプ ID の値に基づいて質問タイプのフィールドの配列を返しています。計算されたプロパティは 13 行目 (App.SurveyContent.types)、およびテンプレート templates/step3 にあります。このアプリは調査以外にも拡張される可能性があるため、「質問」はコード内で「コンテンツ」と呼ばれることが多いことに注意してください。
私は ember にかなり慣れていないので (これは私の最初の実際のアプリです)、私のコードにはこれらの問題以外にも多くの問題がある可能性が高いです.
Javascript エンバー アプリ:
App = Ember.Application.create({
rootElement: '#emberContainer'
});
App.SurveyContent = Ember.Object.extend({
name: "",
content_type: 1,
content_pos: 1,
hash: Em.A([]),
types: function() {
alert("redraw");
return App.ContentTypes[this.content_type-1].hash;
}.property()
});
App.Surveys = Ember.Object.create({
name: null,
start: $.datepicker.formatDate('mm/dd/yy' , new Date()),
end: $.datepicker.formatDate('mm/dd/yy' , new Date()),
themeID: 0,
contents: [App.SurveyContent.create()], //Pushing an instance of App.SurveyContent onto this
contentsNameObserver: function() {
context = this;
console.log("entering");
Em._suspendObserver(App.Surveys, "contents.lastObject.name", false, false, function() {
console.log("suspend handler");
context.contents.pushObject(App.SurveyContent.create());
})
}.observes("contents.lastObject.name")
});
App.ContentTypes = [
Ember.Object.create({name: 'Text question', id:1, hash: [Ember.Object.create({name: 'Question', help: 'Enter the question here', type: 'text'})]}),
Ember.Object.create({name: 'Multichoice question', id:2, hash: [Ember.Object.create({name: 'Question', help: 'Enter the question here', type: 'text'}),
Ember.Object.create({name: 'Answer', help: 'Enter possible answers here', type: 'text', multiple: true})]})
];
App.ViewTypeConvention = Ember.Mixin.create({
viewType: function() {
console.log(this);
return Em.get("Ember.TextField");
}.property().cacheable()
});
App.CRMData = Ember.Object.extend();
App.CRMData.reopenClass ({
crm_data: [],
org_data: [],
org_display_data: [],
loadData: function() {
context = this;
context.crm_data = [];
$.getJSON ("ajax/crm_data", function(data) {
data.forEach(function(crm) {
context.crm_data.pushObject(App.CRMData.create({id: crm.crm_id, name: crm.crm_name}));
crm.orgs.forEach(function(org) {
context.org_data.pushObject(App.CRMData.create({id: org.org_id, name: org.org_name, crm_id: crm.crm_id}));
}, context)
}, context)
context.updateOrganisations(5);
});
return this.crm_data;
},
updateOrganisations: function(crm_id) {
context = this;
this.org_display_data.clear();
console.log("clearing the buffer")
console.log(this.org_display_data)
context.org_data.forEach(function(org) {
if(org.crm_id == crm_id) {
context.org_display_data.pushObject(App.CRMData.create({id: org.id, name: org.name}));
}
}, context)
}
});
App.DateField = Ember.TextField.extend({
attributeBindings: ['id', 'class']
});
App.CRMSelect = Ember.Select.extend({
attributeBindings: ['id'],
change: function(evt) {
console.log(evt)
App.CRMData.updateOrganisations($('#crm').val())
}
});
App.ApplicationController = Ember.Controller.extend();
App.Step1Controller = Ember.ArrayController.extend({});
App.Step2Controller = Ember.ArrayController.extend({});
App.Step2Controller = Ember.ArrayController.extend({});
App.ApplicationView = Ember.View.extend({
templateName: 'app'
});
App.Step0View = Ember.View.extend ({
templateName: 'templates/step0'
});
App.Step1View = Ember.View.extend ({
templateName: 'templates/step1'
});
App.Step2View = Ember.View.extend ({
templateName: 'templates/step2',
didInsertElement: function() {
$( ".jquery-ui-datepicker" ).datepicker();
}
});
App.Step3View = Ember.View.extend ({
templateName: 'templates/step3',
});
App.Router = Em.Router.extend ({
enableLogging: true,
root: Em.Route.extend ({
showstep1: Ember.Route.transitionTo('step1'),
showstep2: Ember.Route.transitionTo('step2'),
showstep3: Ember.Route.transitionTo('step3'),
index: Ember.Route.extend({
route: '/',
connectOutlets: function(router){
router.get('applicationController').connectOutlet( 'step0');
}
}),
step1: Ember.Route.extend ({
route: 'step1',
connectOutlets: function(router){
router.get('applicationController').connectOutlet( 'step1', App.CRMData.loadData());
}
}),
step2: Ember.Route.extend ({
route: 'step2',
connectOutlets: function(router) {
router.get('applicationController').connectOutlet('step2')
},
}),
step3: Ember.Route.extend ({
route: 'step3',
connectOutlets: function(router) {
router.get('applicationController').connectOutlet('step3')
},
})
})
});
Ember.LOG_BINDINGS=true;
App.LOG_BINDINGS = true;
App.ContentTypes.forEach(function(object) {
object.hash.forEach(function(hash) {
hash.reopen(App.ViewTypeConvention);
}, this);
}, this);
Html テンプレート (私はこれらを haml で持っているので、これは重要なものの単なる表現です)
<script type="text/x-handlebars" data-template-name="app">
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="templates/step3">
<h1> Add content to {{App.Surveys.name}} </h1>
<br>
<div id = "accordion2" class = "accordion">
{{#each content in App.Surveys.contents}}
<div class="accordion-group">
<div class = "accordion-heading">
<a class = "accordion-toggle" data-parent = "#accordion2" data-toggle = "collapse" href = "#collapseOne">
{{content.name}}
</a>
</div>
<div id = "collapseOne" class = "accordion-body collapse in">
{{view Ember.TextField valueBinding="content.name" class="txtName"}}
<form class = "form-horizontal">
<div class = "accordion-inner">
<div class = "control-group">
<label class = "control-label" for ="organisation">
Content Type
<div class = "controls">
{{view Ember.Select contentBinding="App.ContentTypes" optionValuePath="content.id" optionLabelPath="content.name" valueBinding="content.content_type"}}
</div>
</div>
</div>
{{#each item in content.types }}
<div class = "control-group" >
<label class = "control-label" for = "organisation">
{{item.name}}
<div class = "controls">
{{view item.viewType }}
</div>
{{/each}}
</div>
</form>
</div>
{{/each}}
</div>
</div>
<br>
<div class = "btn" {:_action => 'showstep3'}> Next Step > </div>
</script>