2014-10-08 39 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