Добавление элемента в отфильтрованный результат из данных ember - PullRequest
8 голосов
/ 03 апреля 2012

У меня есть DS.Store, в котором используются объекты DS.RESTAdapter и ChatMessage, определенные следующим образом:

App.ChatMessage = DS.Model.extend({
    contents: DS.attr('string'),
    roomId:   DS.attr('string')
});

Обратите внимание, что сообщение чата существует в комнате (не показано для простоты), поэтому в моем контроллере сообщений чата (который расширяет Ember.ArrayController) я хочу загружать сообщения только для комнаты, в которой находится пользователь:

loadMessages: function(){ 
    var room_id = App.getPath("current_room.id");
    this.set("content", App.store.find(App.ChatMessage, {room_id: room_id}); 
}

Это устанавливает content в DS.AdapterPopulatedModelArray, и мое представление счастливо отображает все возвращенные сообщения чата в блоке {{#each}}.

Теперь что касается добавления нового сообщения, у меня в том же контроллере есть следующее:

postMessage: function(contents) {
    var room_id = App.getPath("current_room.id");
    App.store.createRecord(App.ChatMessage, {
        contents: contents,
        room_id: room_id
    });

    App.store.commit();
}

Это инициирует ajax-запрос на сохранение сообщения на сервере, пока все хорошо, но это не обновляет представление. Это в значительной степени имеет смысл, поскольку это отфильтрованный результат, и если я удаляю фильтр room_id для App.store.find, он обновляется, как и ожидалось.

Попытка this.pushObject(message) с записью сообщения, возвращенной с App.store.createRecord, вызывает ошибку.

Как вручную добавить элемент в результаты? Насколько я могу судить, пути, по-моему, не существует, так как DS.AdapterPopulatedModelArray и DS.FilteredModelArray неизменны.

Ответы [ 4 ]

8 голосов
/ 19 апреля 2012

так пару мыслей:

(ссылка: https://github.com/emberjs/data/issues/190)

как прослушать новые записи в хранилище данных

нормальная модель.find () / findQuery () вернет вам AdapterPopulatedModelArray, но этот массив будет стоять сам по себе ... он не будет знать, что все новое было загружено в базу данных

Model.find () сникакие параметры (или store.findAll ()) не вернут вам ВСЕ записи FilteredModelArray, а ember-data «зарегистрируют» его в списке, и все новые записи, загруженные в базу данных, будут добавлены в этот массив.

вызов Model.filter (func) вернет вам FilteredModelArray, который также зарегистрирован в хранилище ... и любые новые записи в хранилище приведут к тому, что ember-data будет "updateModelArrays", то есть вызовет вашу функцию фильтрас новой записью, и если вы вернете true , то он вставит ее в ваш существующий массив.

ТАК, ЧТО Я ЗАКОНЧИЛ ДЕЛАТЬ: было сразу после создания хранилища, я вызываю store.findAll (), который возвращает мне массив всех моделей для типа ... и я присоединяю его к хранилищу ... затем в любом месте кода, я могу добавить ArrayObservers в эти списки ... что-то вроде:

App.MyModel = DS.Model.extend()
App.store = DS.Store.create()
App.store.allMyModels = App.store.findAll(App.MyModel)

//some other place in the app... a list controller perhaps
App.store.allMyModels.addArrayObserver({
   arrayWillChange: function(arr, start, removeCount, addCount) {}
   arrayDidChange: function(arr, start, removeCount, addCount) {}
})

как вставить модель в один из этих «неизменяемых» массивов:

Первое, что нужно отметить: все экземпляры (записи) модели Ember-Data имеют clientIdсвойство ... которое является уникальным целым числом, которое идентифицирует модель в кэше хранилища данных независимо от того, имеет ли он реальный идентификатор сервера (пример: сразу после выполнения Model.createRecord).

, поэтому сам AdapterPopulatedModelArray имеет свойство "content" ... которое является массивом этих clientId ... и когда вы перебираете AdapterPopulatedModelArray, итератор зацикливается на этих clientId и возвращает вам полную модельэкземпляры (записи), которые сопоставляются с каждым clientId.

ТАК ЧТО Я СДЕЛАЛ (это не значит, что это "правильно"!) - это наблюдать за этими массивами findAll и выдвигать новые clientIdв свойство содержимого AdapterPopulatedModelArray ... ЧТО-ТО КАК:

arrayDidChange:function(arr, start, removeCount, addCount){
    if (addCount == 0) {return;} //only care about adds right now... not removes...
        arr.slice(start, start+addCount).forEach(function(item) {
            //push clientId of this item into AdapterPopulatedModelArray content list
            self.getPath('list.content').pushObject(item.get('clientId'));
        });
    }

, что я могу сказать: "это работает для меня" :) не сломается ли при следующем обновлении ember-data?вполне возможно

2 голосов
/ 02 октября 2013

Для тех, кто все еще борется с этим, вы можете получить динамический DS.FilteredArray вместо статического DS.AdapterPopulatedRecordArray, используя метод store.filter . принимает 3 параметра : тип, запрос и, наконец, обратный вызов фильтра.

loadMessages: function() { 
  var self = this,
      room_id = App.getPath('current_room.id');

  this.store.filter(App.ChatMessage, {room_id: room_id}, function (msg) {
    return msg.get('roomId') === room_id;
  })
  // set content only after promise has resolved
  .then(function (messages) {
    self.set('content', messages);
  });         
}

Вы также можете сделать это в хуке модели без лишнего беспорядка, потому что хук модели приметобещаю прямо:

model: function() { 
  var self = this,
      room_id = App.getPath("current_room.id");

  return this.store.filter(App.ChatMessage, {room_id: room_id}, function (msg) {
    return msg.get('roomId') === room_id;
  });
}
0 голосов
/ 06 мая 2018

По состоянию на ember.data 1.13 store.filter был отмечен для удаления, см. Следующее сообщение в блоге ember .

Функция была сделана доступной как миксин . Страница GitHub содержит следующую заметку

Мы рекомендуем вам отказаться от использования этого дополнения. Ниже приведено краткое руководство по трем сценариям использования фильтров и тому, как наилучшим образом реорганизовать каждый из них.

Почему? Проще говоря, гораздо эффективнее (а не утечка памяти) вам управлять фильтрацией самостоятельно через специализированное вычисляемое свойство, специально разработанное для ваших нужд

0 голосов
/ 08 апреля 2012

Мое чтение источника (DS.Store.find) показывает, что в данном случае вы фактически получаете AdapterPopulatedModelArray.FilteredModelArray будет автоматически обновляться при создании записей.Есть проходящие тесты для этого поведения.

...