2012-04-03 9 views
8

Ich habe eine DS.Store die die DS.RESTAdapter verwendet und ein ChatMessage Objekt definiert als solche:Artikel wird hinzugefügt, um gefilterte Ergebnis von Ember-Daten

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

Beachten Sie, dass eine Chat-Nachricht existiert in einem Raum (der Einfachheit halber nicht gezeigt) , so in meinem Chat-Nachrichten-Controller nur (die Ember.ArrayController erstreckt) ich will, ist der Anwender für den Raum-Nachrichten laden in:

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

Hier wird die content auf eine DS.AdapterPopulatedModelArray und meine Ansicht zeigt glücklich alle zurückgegebenen Chat-Nachrichten in einem {{#each}} Block an.

Jetzt kommt es eine neue Nachricht zu geben, habe ich im Anschluss an den in demselben Controller:

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

Dies löst eine Ajax-Anforderung die Nachricht auf dem Server zu speichern, alles so weit gut, aber es doesn Aktualisieren Sie die Ansicht nicht. Dies macht ziemlich viel Sinn, da es ein gefiltertes Ergebnis ist und wenn ich den room_id Filter auf App.store.find entferne, dann wird es wie erwartet aktualisiert.

Wenn Sie versuchen, this.pushObject(message) mit dem Nachrichtendatensatz zu senden, der von App.store.createRecord zurückgegeben wird, wird ein Fehler ausgegeben.

Wie kann ich den Artikel manuell zu den Ergebnissen hinzufügen? Soweit ich das beurteilen kann, scheint es keinen Weg zu geben, da sowohl als auch DS.FilteredModelArray unveränderlich sind.

Antwort

0

Mein Lesen der Quelle (DS.Store.find) zeigt, dass Sie in diesem Fall tatsächlich ein AdapterPopulatedModelArray erhalten würden. Ein FilteredModelArray wird beim Erstellen von Datensätzen automatisch aktualisiert. Es gibt bestandene Tests für dieses Verhalten.

+0

Du hast Recht, es ist ein AdapterPopulatedModelArray. Ich habe die Frage aktualisiert - Entschuldigung für den Tippfehler! – rlivsey

8

so paar Gedanken:

(Referenz: https://github.com/emberjs/data/issues/190)

wie für neue Datensätze im Datenspeicher

ein normaler Model.find()/findQuery() hören zurückkehren Sie ein AdapterPopulatedModelArray, aber dieses Array wird für sich selbst stehen ... es wird nicht wissen, dass etwas Neues in die Datenbank geladen wurde

ein Model.find() ohne Par ams (oder store.findAll()) gibt Ihnen ALLE Datensätze ein FilteredModelArray zurück, und ember-data wird es in einer Liste "registrieren", und alle neuen Datensätze, die in die Datenbank geladen werden, werden zu diesem Array hinzugefügt.

Aufruf Model.filter (func) werden Sie zurück geben einen FilteredModelArray, die auch mit dem Speicher registriert ist ... und alle neuen Einträge in den Laden glut-Daten zu „updateModelArrays“ verursachen, was bedeutet, es wird rufen Sie Ihren Filterfunktion mit dem neuen Datensatz, und wenn Sie true zurückgeben, dann wird es es in Ihr bestehendes Array stecken.

SO WAS ICH ENDED UP DOING: wurde sofort nach dem Erstellen des Speichers, ich store.findAll() aufrufen, die mir ein Array aller Modelle für einen Typ zurückgibt ... und ich das an den Laden anhängen .. Dann kann ich irgendwo anders im CodeArrayObservers zu diesen Listen hinzufügen.so etwas wie:

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) {} 
}) 

wie ein Modell in eine dieser „unveränderlich“ Arrays drücken:

Erster zu beachten: alle Ember-Datenmodell Instanzen (Aufzeichnungen) eine clientId Eigenschaft ... Dies ist eine eindeutige Ganzzahl, die das Modell im Datenspeicher-Cache identifiziert, unabhängig davon, ob es eine echte Server-ID gibt (Beispiel: direkt nach dem Ausführen von Model.createRecord). Das AdapterPopulatedModelArray selbst hat also eine "content" -Eigenschaft ... welches ein Array dieser clientId's ist ... und wenn Sie über das AdapterPopulatedModelArray iterieren, führt der Iterator eine Schleife über diese clientId's aus und gibt Ihnen die vollständigen Model-Instanzen zurück (Datensätze), die jeder clientId zugeordnet werden.

SO was ich getan habe (! Das bedeutet nicht, es ist „rechts“) ist es, die findAll Arrays zu sehen, und schieben neue clientId die in den Inhalt Eigentum der AdapterPopulatedModelArray ... so etwas wie:

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

was ich sagen kann ist: "es funktioniert für mich" :) wird es bei der nächsten ember-daten update brechen? durchaus möglich

2

diejenigen Für noch kämpfen mit diesem, können Sie sich eine dynamische DS.FilteredArray anstelle einer statischen DS.AdapterPopulatedRecordArray unter Verwendung des store.filter Methode erhalten. Es takes 3 parameters: Typ, Abfrage und schließlich ein Filter Rückruf.

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

Sie auch dies ohne die zusätzliche Unordnung im Modell Haken tun könnten, weil das Modell Haken direkt ein Versprechen akzeptieren:

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; 
    }); 
} 
Verwandte Themen