Ember.js计算属性过滤器hasMany数组

时间:2014-10-08 22:40:40

标签: ember.js ember-data

我正在尝试过滤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';
}),
'surveyQuestionType'是DS.belongsTo,它存在于'subquestions'的模型中,并且具有'name'属性。

我想理解为什么'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' })
});

2 个答案:

答案 0 :(得分:5)

我花了更多的时间用自己的工作来发现这类问题而不是我承认,但幸运的是,解决方案很简单。在DS.Model定义中,surveyQuestionTypebelongsTo的关系是{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将为空。