2012-05-18 1 views
13

Vorrei accedere ai campi calcolati che ho implementato nel modello (backbone.js) dal modello. Devo sempre definire un helper per farlo?Come accedere a un campo calcolato di un modello backbone dal modello di manubri?

Penso che il problema abbia a che fare con il modo in cui passo il modello al modello. Se passo this.model.toJSON() ho accesso alle proprietà ma non alle funzioni che ho definito al suo interno. Se passo direttamente questo modello, posso accedere alla funzione ma non alle proprietà del modello di backbone.

+0

penso che il problema ha a che fare con il modo in cui passo il modello per il modello. – Juanma

risposta

17

Sempre passare this.model.toJSON() ai modelli.

Ciò che è necessario fare per ottenere i valori calcolati, ha la precedenza sul metodo toJSON sul modello.


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

}) 

e ora avete accesso a myValue dalla JSON restituito da toJSON, il che significa che si ha accesso ad esso nella vista.

L'altra opzione, come hai detto, è quella di creare metodi di supporto e registrarli con Handlebars. A meno che tu non abbia alcune funzionalità che cambiano in base a come viene eseguito il rendering del modello e/o quali dati vengono passati al modello, non mi preoccuperei di ciò.

+10

C'è uno svantaggio nell'override di 'toJSON':' Backbone.sync' usa 'toJSON' per serializzare i modelli (più precisamente,' sync' chiama 'JSON.stringify' che chiama' toJSON' quindi ora il server vedrà 'myValue 'anche se probabilmente non gliene importa. Questo potrebbe o non potrebbe essere un problema. –

+0

Grazie mille. – Juanma

0

Ho avuto lo stesso problema. @DerickBailey ha ragione, ovviamente, che ignorare toJSON fa il lavoro. Ma trapelano anche nella comunicazione con il server (vedi il commento di Muu sulla sua risposta).

Quindi, alla fine, ho creato un plug-in Backbone per gestire specificamente l'esportazione dei dati nei template e farlo con un minimo di confusione: Backbone.Marionette.Export. Si occupa anche di strutture annidate, cura i riferimenti circolari, ecc. Vedi docs.

Ecco come funziona. Includere il file plug-in nel progetto e dichiarare

MyModel = Backbone.Model.extend({ 

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

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

}); 

Se sei un utente burattino, si è già fatto, a questo punto. foo compare nei tuoi modelli come se fosse un attributo di modello.

Nelle normali viste Backbone, è sufficiente chiamare myModel.export() o myCollection.export() anziché le controparti toJSON quando si esegue il rendering.

Per i metodi che accettano argomenti, esiste un gestore onExport. Gli esempi, ancora, sono nello docs.

-1

Il modo migliore per farlo è quello di aggiungere questo al modello:

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

Un modello dorsale memorizza normalmente i valori effettivi dei dati internamente "model.attributes". Ecco perché quando si passa il modello direttamente al modello, ha solo funzioni aggiunte direttamente al modello e non a nessun dato. E se usi model.toJSON() normalmente viene implementato in backbone come _.clone (model.attributes) (vedi backbone.js). Quindi hai i dati e non le funzioni aggiunte direttamente al modello. Ecco perché funziona sopra: si imposta la funzione su model.attributes, non sull'oggetto modello stesso. Non fare riferimento direttamente a model.attributes, utilizzare model.get ("calculateColumn") e model.set ("calculateColumn", ...).

Quindi modello.get ("calculateColumn") restituisce una funzione. Se vai {{calculateColumn}} nel manubrio (supponendo che tu stia usando il manubrio), mostra il valore restituito dalla funzione. Ma calculateColumn non verrà inviato al server perché backbone esegue un JSON.stringify su model.toJSON in sync (in backbone.js) e JSON.stringify ignora le funzioni. Se si desidera che JSON.stringify non ignori la funzione (quindi la funzione viene trasformata in un valore di dati ogni volta che JSON viene eseguito sul modello - durante il rendering della vista e la sincronizzazione del modello), sovrascrivere model.toJSON come descritto da @Derick Bailey.

Inoltre, è possibile derivare il proprio BaseModel da Backbone.Model e sovrascrivere .toJSON e derivare tutti i modelli da BaseModel se necessario. Allora avresti bisogno di una versione generica di .toJSON che possa essere applicata a qualsiasi modello.

4

Ecco un'altra possibilità: (dal modello di inizializzazione)

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

Computed properties in Backbone