2012-05-18 12 views
13

Chciałbym uzyskać dostęp do pól obliczonych zaimplementowałem w modelu (backbone.js) z szablonu. Czy muszę zawsze zdefiniować pomocnika, aby to zrobić?Jak uzyskać dostęp do obliczonego pola modelu szkieletowego z szablonu kierownicy?

Myślę, że problem dotyczy sposobu, w jaki przekazuję model do szablonu. Jeśli przekażę this.model.toJSON(), mam dostęp do właściwości, ale nie do funkcji, które w nim zdefiniowałem. Jeśli przekazuję this.model bezpośrednio, mogę uzyskać dostęp do funkcji, ale nie do właściwości modelu szkieletowego.

+0

Myślę, że problem ma związek ze sposobem Mijam modelu do szablonu. – Juanma

Odpowiedz

17

Zawsze przekazuj this.model.toJSON() do swoich szablonów.

To, co należy zrobić, aby otrzymać obliczone wartości, jest nadrzędne w stosunku do metody toJSON w modelu.


MyModel = Backbone.Model.extend({ 

    myValue: function(){ 
    return "this is a calculated value"; 
    }, 

    toJSON: function(){ 
    // get the standard json for the object 
    var json = Backbone.Model.prototype.toJSON.apply(this, arguments); 

    // get the calculated value 
    json.myValue = this.myValue(); 

    // send it all back 
    return json; 
    } 

}) 

A teraz masz dostęp do myValue z JSON, który jest zwracany przez toJSON, co oznacza, że ​​masz do niego dostęp w widoku.

Inną opcją, o której wspomniałeś, jest zbudowanie metod pomocniczych i zarejestrowanie ich za pomocą Handlebars. Jeśli nie masz jakiejś funkcjonalności, która zmienia się w zależności od tego, jak szablon jest renderowany i/lub jakie dane są przekazywane do szablonu, nie zawracałbym sobie tym głowy.

+10

Wadą jest przesłonięcie 'toJSON':' Backbone.sync' używa 'toJSON' do serializowania modeli (dokładniej,' sync' wywołuje 'JSON.stringify', który wywołuje' toJSON'), więc teraz serwer zobaczy 'myValue 'chociaż prawdopodobnie o to nie dba. To może, ale nie musi być problem. –

+0

Dziękuję bardzo. – Juanma

0

Miałem ten sam problem. @DerickBailey ma oczywiście rację, że nadpisanie JSON wykonuje tę pracę. Ale przecieka również do komunikacji z serwerem (patrz komentarz muu na jego odpowiedź).

W końcu zbudowałem wtyczkę kręgosłupa, aby w szczególny sposób obsługiwać eksport danych do szablonów, i zrobić to przy minimalnym zamieszaniu: Backbone.Marionette.Export. Zajmuje się również strukturami zagnieżdżonymi, zajmuje się odwołaniami cyklicznymi itp. Zobacz: docs.

Oto jak to działa. Dołączyć plik wtyczki do projektu i deklarują

MyModel = Backbone.Model.extend({ 

    foo: function() { 
     return "I am a calculated value"; 
    }, 

    exportable: "foo" // <-- this is the one line you have to add 

}); 

Jeśli jesteś użytkownikiem Marionette, jesteś już zrobić w tym momencie. foo pojawia się w szablonach tak, jakby był atrybutem modelu.

W prostych widokach kręgosłupa po prostu wywołaj myModel.export() lub myCollection.export() zamiast ich odpowiedników toJSON, gdy renderujesz.

W przypadku metod przyjmujących argumenty istnieje procedura obsługi onExport. Przykłady, znowu, są w docs.

-1

Najlepszym sposobem, aby to zrobić jest dodanie do tego modelu:

function initialize() { 
    this.set("calculatedColumn", function() { return this.otherColumn; }); 
} 

Model kręgosłup normalnie zapamiętuje wartości rzeczywiste dane wewnętrznie w "model.attributes". Dlatego kiedy przekazujesz model bezpośrednio do szablonu, ma on tylko funkcje dodane bezpośrednio do modelu, a nie dane. A jeśli użyjesz metody model.toJSON(), zwykle jest ona implementowana w szkielecie jako _.clone (model.attributes) (patrz backbone.js). Masz więc dane, a nie funkcje dodane bezpośrednio do modelu. Dlatego powyższe działa - ustawiasz funkcję na model.attributes, a nie na samym obiekcie modelu. Nie odwołuj się bezpośrednio do pliku model.attributes, użyj modelu.get ("calculColumn") i model.set ("calculColumn", ...).

Model.get ("calculColumn") zwraca funkcję. Jeśli podążasz {{calculcolumn}} w kierownicy (zakładając, że używasz kierownicy), pokazuje ona wartość zwróconą przez funkcję. Ale obliczona kolumna nie zostanie wysłana do serwera, ponieważ szkielet wykonuje synchronizację JSON.stringify z model.toJSON (w backbone.js) i JSON.stringify ignoruje funkcje. Jeśli chcesz, aby funkcja JSON.stringify nie ignorowała funkcji (tak, aby funkcja była przekształcana w wartość danych, ilekroć JSON jest uruchamiany w modelu - podczas wyświetlania widoku i synchronizacji modelu), przesłonić model.toJSON tak, jak opisano @Derick Bailey.

Można również wyprowadzić własny model bazowy z Backbone.Model i zastąpić .toJSON i wyprowadzić wszystkie modele z BaseModel, jeśli zajdzie taka potrzeba. Wtedy potrzebowalibyśmy ogólnej wersji .toJSON, którą można zastosować do dowolnego modelu.

4

Oto inna możliwość: (od modelu initialize)

initialize: function() { 
     this.on("change", function() { 
      this.set({ calculatedColumn: this.get("otherColumn") }, { silent: true }); 
     }); 
    }, 

Computed properties in Backbone

Powiązane problemy