我正在尝试过滤ember-data'hasMany'字段的内容。我的模型有一些子参数,我想在我的控制器上过滤到属性'childOptions'并使用
显示在模板中{{#each childOptions}}stuff{{/each}}
当我把它放在我的控制器上时,它可以工作,并且每个都迭代适当的值:
childOptions: Ember.computed.filterBy('model.subquestions', 'surveyQuestionType.name', 'childOption'),
然而,当我这样做时,没有显示任何内容。
childOptions: Ember.computed.filter('model.subquestions', function(subquestion) {
return subquestion.get('surveyQuestionType.name') === 'childOption';
}),
我想理解为什么'filterBy'方法有效,而'filter'方法却没有(因此我可以在将来使用'filter'进行更复杂的查询)。我认为这与promises和我在filter函数中使用的subquestion.get('property')
语法有关。
编辑:
这是模型:
App.SurveyQuestion = DS.Model.extend(Ember.Validations.Mixin, {
surveyQuestionType: DS.belongsTo('surveyQuestionType', { async: true }),
display: DS.belongsTo('surveyQuestionDisplay', { async: true, inverse: 'surveyQuestion' }),
sortOrder: DS.attr('number'),
parent: DS.belongsTo('surveyQuestion', { async: true, inverse: 'subquestions' }),
parentDependencyCriteria: DS.attr('string'),
required: DS.attr('boolean'),
surveySections: DS.hasMany('surveySectionQuestion', { async: true, inverse: 'surveyQuestion' }),
subquestions: DS.hasMany('surveyQuestion', { async: true, inverse: 'parent' })
});
答案 0 :(得分:5)
我花了更多的时间用自己的工作来发现这类问题而不是我承认,但幸运的是,解决方案很简单。在DS.Model
定义中,surveyQuestionType
与belongsTo
的关系是{async: true}
吗?如果是这样,那就是你的问题。
每当您在DS.Model
中设置{async: true}
关系时,您可以将其视为实际设置承诺,以便最终获得该属性。这很有意义并且变得直观,但是没有记录得很好!
对于初学者来说,Promise尤其棘手,因为你的Handlebars模板将透明地处理{{surveyQuestionType.name}}
surveyQuestionType
是具体值还是承诺。这让初学者感到困惑,因为如果Handlebars呈现出具体的价值或承诺,你就不能乍一看。
当您处理承诺时,您可以直接访问承诺在其content
属性中解析的内容。实际上,您甚至可以设置content
属性。但要小心这一点,因为直接读取/写入content
属性对承诺可能具有的任何挂起操作没有影响。因此,如果在写入content
值时承诺仍处于暂挂状态,则一旦结算,您的写入将被覆盖。
当我添加新实体并需要填充承诺关系时,我直接写入content
属性。这在那里是有意义的,但是如果我正在阅读一个值,我需要找到一些方法来保证我在阅读content
属性时承诺已经解决了......或者,我可以让Handlebars直接处理这个问题,因为我知道对于纯粹的显示逻辑,我并不关心延迟150毫秒。
无论如何,如果上述所有内容都适用于您的问题,请按以下步骤编辑代码以使其正常运行:
childOptions: Ember.computed.filter('model.subquestions', function(subquestion) {
return subquestion.get('surveyQuestionType.content.name') === 'childOption';
})
更新#1:我认为我没有仔细访问content
,而是违反了我自己的建议。有关调试的信息,请参阅我的注释,您也可以尝试这样做:
childOptions: Ember.computed.filter('model.subquestions', function(subquestion) {
return subquestion.get('surveyQuestionType').then( function( model ) {
return model.get('name') === 'childOption';
});
})
更新#2:请参阅下面的评论,特别是https://github.com/emberjs/data/issues/1865。事实证明这是一个棘手的问题,我欢迎其他人的意见,以澄清这里的最佳方法。
我通过处理上游的promises在我自己的代码中解决了这个问题,这样我就可以直接访问content
属性,或者根本不处理我的过滤器中的promises。
答案 1 :(得分:2)
从ember-data 1.0.0-beta.11开始,承诺似乎工作更顺畅,我在这方面取得了成功(我实际上采用了不同的方法处理我的原始问题,但在类似的情况下使用了此代码) :
childOptions: function() {
var subquestions = this.get('subquestions');
if (subquestions) {
return subquestions.filter(function(subquestion) {
var surveyQuestion = subquestion.get('surveyQuestion');
return (surveyQuestion && surveyQuestion.get('name') === 'childOptions');
});
}
}.property('subquestions.@each.surveyQuestion')
.property('subquestions.@each.surveyQuestion')
导致在surveyQuestion
承诺解决时更新属性。如果您输入一些输出,您将看到最初调用该属性并且subquestions
将为空。