Javascript 余烬绑定在不需要时发射,在需要时不发射
嘿,我的ember应用程序中有两个不同的问题,都涉及绑定 首先,我有一个绑定射击,当我不想它。基本上,我试图实现的(我正在构建一个survey creator前端应用程序)是,当任何文本输入到问题的“名称”字段时,我想添加一个新的问题对象,这将在用户添加的问题列表末尾呈现另一个空白问题。这会产生一个新问题的效果,因此不需要“添加问题”按钮。绑定正在工作,并且正在添加一个新对象:但是,由于绑定来自最新的问题对象,因此在创建新对象时会再次触发绑定,这反过来又会创建一个新对象,再次触发绑定……这显然最终会使浏览器崩溃。我尝试过使用Ember.\u suspendObserver函数,但是没有太多关于这个的文档,我认为我用错了-无论如何,它不是挂起观察者或暂停绑定。代码中的观察者位于第27行附近(contentsNameObserver) 我遇到的另一个问题是——我有一个选择下拉框,它选择用户想要的问题类型(单答案、多选等),但是选择框和{{each}}帮助器之间的绑定不会触发这种问题。我正在使用Ember.Select视图助手,因此使用get/set启动绑定应该不会有任何问题。我正在使用计算属性根据问题类型id的值返回问题类型的字段数组。计算属性位于第13行(App.SurveyContent.types)和模板模板/step3中。快速提示:此应用程序可以扩展到多个调查,因此“问题”在代码中通常被称为“内容” 我是ember的新手(这是我第一个真正的应用程序),所以我的代码很可能除了这些问题之外还有很多问题……因此,如果您对我如何构建我的应用程序有任何评论,我将不胜感激 Javascript余烬应用程序:Javascript 余烬绑定在不需要时发射,在需要时不发射,javascript,ember.js,Javascript,Ember.js,嘿,我的ember应用程序中有两个不同的问题,都涉及绑定 首先,我有一个绑定射击,当我不想它。基本上,我试图实现的(我正在构建一个survey creator前端应用程序)是,当任何文本输入到问题的“名称”字段时,我想添加一个新的问题对象,这将在用户添加的问题列表末尾呈现另一个空白问题。这会产生一个新问题的效果,因此不需要“添加问题”按钮。绑定正在工作,并且正在添加一个新对象:但是,由于绑定来自最新的问题对象,因此在创建新对象时会再次触发绑定,这反过来又会创建一个新对象,再次触发绑定……这显然最
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中有这些模板,所以这只是一些重要模板的表示)
{{outlet}}
向{{App.Surveys.name}添加内容
{{{#App.Surveys.contents中的每个内容}
{{view Ember.TextField valueBinding=“content.name”class=“txtName”}
内容类型
{{view Ember.Select contentBinding=“App.ContentTypes”optionValuePath=“content.id”optionLabelPath=“content.name”valueBinding=“content.content\u type”}
{{{#content.types中的每个项目}
{{item.name}
{{view item.viewType}
{{/每个}}
{{/每个}}
'showstep3'}>下一步>
我已经解决了第一个问题,尽管我没有让suspendObserver属性工作,但我使用了一个if语句来检查前面的元素,从而删除了无限循环
contentsNameObserver: function() {
context = this;
if(this.get('contents.lastObject').name) {
context.contents.pushObject(App.SurveyContent.create());
}
}.observes("contents.lastObject.name")
任何关于如何让suspendObserver处理程序工作的评论都将不胜感激,虽然这应该可以工作,但我做错了
我已经在
它被设置为直接进入问题步骤,步骤3,这样我就不需要包括前面的所有模板
不过,我仍然被束缚在捆绑不开火的问题上。我期望的行为是,当“内容类型”下拉框更改时,下面的文本框应该更改,它应该用两个文本框重新呈现。我意识到这是一个老问题,但也没有文档和我可以在搜索中找到的宝贵信息,因此分享我在这里找到的有用信息 我发现有效的方法是调用
Ember.\u suspendObserver
,如下所示:
somePropertyDidChange: function(key) {
var that = this;
Ember._suspendObserver(this, key, null,
'somePropertyDidChange', function() {
// do stuff which would normally cause feedback loops
that.set('some.property', 'immune to feedback');
});
}.observes('some.property');
somePropertiesDidChange: function(key) {
var that = this;
Ember._suspendObservers(this, ['some.property', 'another.property'],
null, 'somePropertiesDidChange', function() {
// do stuff which would normally cause feedback loops
that.set('some.property', 'immune to feedback');
that.set('another.property', 'also immune to feedback');
});
}.observes('some.property', 'another.property');
您还可以使用多观察者变量,如下所示:
somePropertyDidChange: function(key) {
var that = this;
Ember._suspendObserver(this, key, null,
'somePropertyDidChange', function() {
// do stuff which would normally cause feedback loops
that.set('some.property', 'immune to feedback');
});
}.observes('some.property');
somePropertiesDidChange: function(key) {
var that = this;
Ember._suspendObservers(this, ['some.property', 'another.property'],
null, 'somePropertiesDidChange', function() {
// do stuff which would normally cause feedback loops
that.set('some.property', 'immune to feedback');
that.set('another.property', 'also immune to feedback');
});
}.observes('some.property', 'another.property');
在我的具体用例中,我实际上调用了
Ember.\u suspendobserver
函数,该函数是由观察者设置的Ember.run.once()
函数,因为我想确保在进行计算之前解决了许多依赖属性,这些属性反过来会改变其中的一些属性。请创建jsfiddle。。