2014-10-08 37 views
3

我试图过滤一个花费数据'hasMany'字段的内容。我的模型具有一定的子问题,我想用Ember.js计算属性过滤器hasMany数组

{{#each childOptions}}stuff{{/each}} 

当我把这个我控制器上渗入到我的控制器和显示在模板上的属性“childOptions”,它的工作原理,并在适当的值的每个迭代:

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,它有一个“名称”属性。

我想了解为什么'filterBy'方法有效,而'filter'方法没有(为了将来可以使用'filter'来处理更复杂的查询)。我认为它与Promise和我在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

'subquestion.get('surveyQuestionType.name')''undefined',我很确定是这个问题,但我不知道如何解决它!如果我在模板中做了一个简单的'{{#each subquestions}} {{surveyQuestionType.name}} {{/ each}}',我可以看到该属性就好了。 – leejt489 2014-10-08 22:45:13

回答

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('[email protected]') 

.property('[email protected]')导致当surveyQuestion承诺解决要更新的属性。如果你输入一些输出,你会看到最初的属性被调用,subquestions将为空。

+0

忽略“if(subquestions)”,并在每个使用函数的地方添加.property(“childOptions”)。没有测试它,但应该工作。我用.any而不是过滤器,它的工作原理。 – goutham 2015-01-24 20:05:38

5

我花了更多的时间比我愿意承认,但幸运的是解决方案是简单的这一类问题的发现与我自己的工作。在你的DS.Model定义中,是surveyQuestionType a belongsTo{async: true}的关系?如果是这样,那就是你的问题。

每当你在你的DS.Model{async: true}的关系,你可以把它作为实际设置承诺,你最终会得到该属性。这是有道理的,并变得直观,但它没有很好地记录!

承诺是对初学者尤其棘手,因为你的车把模板将透明地处理{{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我的意见。事实证明这是一个棘手的问题,我希望其他人的意见能够澄清这里的最佳做法。

我已经在自己的代码中解决了这个问题,通过处理上游的承诺,以便我可以直接访问content属性,或者在我的过滤器中完全不处理承诺。

+0

感谢您的解释,并且您对'async:true'的描述是正确的。尽管你的答案并不完美。这可能是子问题属性也是一个promise数组。另外,使用'Ember.computed.filter'时不需要'.property()'?理想情况下,我希望在承诺解决后进行筛选,对吗? – leejt489 2014-10-09 02:07:30

+0

Re:'.property()',你是正确的,并指出这一点。我会更新我的答案。很快会回应其他问题。 – 2014-10-09 02:38:42

+0

Re:这不行,我有两个想法。 (1)确切知道你正在处理的每个实体是什么是有帮助的。所以,试一下'console.log(this.get('model.subquestions')。toString())'这会告诉你它是一个承诺还是具体的价值。你也应该看看优秀的http://eviltrout.com/2014/08/16/debugging-ember-js.html。 (2)我可能在我原来的答案中犯了一个错误,因为我从一个承诺中访问了内容,但是这个代码不会等到这个承诺被解析为读取这个值。查看更新后的答案。对于原始回复中的错误感到抱歉。 – 2014-10-09 02:44:32