2014-10-08 4 views
3

Я пытаюсь отфильтровать содержимое поля hasMany в ember-data. Моя модель имеет некоторые подвопросы, которые я хочу, чтобы просочиться в свойство «childOptions» на мой контроллер и дисплей в шаблоне с помощьюEmber.js вычисленный фильтр свойств hasMany array

{{#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, которая существует на модели «подвопросы», и он имеет свойство «имя».

Я хочу понять, почему работает метод filterBy, в то время как метод «фильтр» (так что я могу использовать «фильтр» для более сложных запросов в будущем). Я думаю, что это имеет какое-то отношение к обещаниям и синтаксис subquestion.get('property'), который я использую внутри функции фильтра.

EDIT:

Это модель:

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

ответ

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 будет равно NULL.

+0

«if (subquestions)» игнорируется и добавляет .property («childOptions»), где каждая функция используется. не тестировал, но должен работать. Я использовал .any вместо фильтра, и он работает. – goutham

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'; 
}) 

UPDATE # 1: Я считаю, что только нарушил свою собственную рекомендацию не доступ к content задумчиво. Смотрите мои комментарии для информации об отладке, и вы можете попробовать это:

childOptions: Ember.computed.filter('model.subquestions', function(subquestion) { 
    return subquestion.get('surveyQuestionType').then(function(model) { 
     return model.get('name') === 'childOption'; 
    }); 
}) 

UPDATE # 2: Смотрите мои комментарии ниже, и в частности https://github.com/emberjs/data/issues/1865. это оказалось более сложной проблемой, и я хотел бы приветствовать вклад других, чтобы прояснить наилучший подход здесь.

Я решил эту проблему в своем собственном коде, обратившись с обещаниями вверх по течению, чтобы я мог напрямую получить доступ к свойству content или вообще не иметь дело с обещаниями вообще в своих фильтрах.

+0

Спасибо за объяснение, и вы правы в 'async: true'. Однако ваш ответ не совсем работает. Может быть, свойство subquestsions также является массивом обещаний. Кроме того, не является ли добавление '.property()' излишним при использовании 'Ember.computed.filter'? В идеале я хочу что-то, что фильтрует после того, как обещание будет разрешено, не так ли? – leejt489

+0

Re: '.property()', вы правы и THX для указания этого. Я уточню свой ответ. В ближайшее время ответит на другие вопросы. –

+0

Re: это не работает, у меня две мысли. (1) Полезно знать, с какими сущностями вы сталкиваетесь. Итак, попробуйте 'console.log (this.get ('model.subquestions'). ToString())' Это скажет вам, является ли это обещанием или конкретным значением. Вы также должны посмотреть на отличный http://eviltrout.com/2014/08/16/debugging-ember-js.html. (2) Возможно, я допустил ошибку в своем первоначальном ответе, потому что я получил доступ к контенту из обещания, но этот код не ждет, пока обещание не решит прочитать значение. Проверьте обновленный ответ. Извините за ошибки в исходном ответе. –

Смежные вопросы