2012-05-18 10 views
13

Me gustaría acceder a los campos calculados que he implementado en el modelo (backbone.js) desde la plantilla. ¿Debo definir siempre un ayudante para hacerlo?¿Cómo acceder a un campo calculado de un modelo de red troncal desde la plantilla de barras de control?

Creo que el problema tiene que ver con la forma en que paso el modelo a la plantilla. Si paso this.model.toJSON() tengo acceso a las propiedades pero no a las funciones que he definido en él. Si paso este modelo directamente, puedo acceder a la función pero no a las propiedades del modelo de red troncal.

+0

creo que el problema tiene que ver con la forma en que paso por el modelo de la plantilla. – Juanma

Respuesta

17

Pase siempre this.model.toJSON() a sus plantillas.

Lo que necesita hacer para obtener sus valores calculados, es anular su método toJSON en su modelo.


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

}) 

Y ahora tienen acceso a la myValue del JSON devuelto por toJSON, lo que significa que tiene acceso a ella en la vista.

La otra opción, como mencionó, es crear métodos de ayuda y registrarlos con manubrios. A menos que tenga alguna funcionalidad que cambie según la forma en que se está procesando la plantilla y/o los datos que se pasan a la plantilla, no me molestaría con eso.

+10

Hay una desventaja al anular 'toJSON':' Backbone.sync' utiliza 'toJSON' para serializar modelos (más precisamente, llamadas' sync' 'JSON.stringify' que llama' toJSON') así que ahora el servidor verá 'myValue 'a pesar de que probablemente no le importe. Esto puede o no ser un problema. –

+0

Muchas gracias. – Juanma

0

He tenido el mismo problema. @DerickBailey tiene razón, por supuesto, que reemplazar a JSON hace el trabajo. Pero también se filtra en la comunicación con el servidor (ver el comentario de muu sobre su respuesta).

Así que eventualmente, he construido un complemento Backbone para manejar específicamente la exportación de datos a plantillas, y lo hago con un mínimo de alboroto: Backbone.Marionette.Export. También se ocupa de estructuras anidadas, se ocupa de referencias circulares, etc. Consulte el docs.

Así es como funciona. Incluir el archivo plugin en su proyecto y declarar

MyModel = Backbone.Model.extend({ 

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

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

}); 

Si usted es un usuario de marionetas, ya está terminado en este punto. foo aparece en sus plantillas como si fuera un atributo de modelo.

En vistas de Backbone planas, simplemente llame a myModel.export() o myCollection.export() en lugar de sus contrapartes de toJSON cuando realice la renderización.

Para los métodos que toman argumentos, hay un controlador onExport. Los ejemplos, de nuevo, están en el docs.

-1

La mejor manera de hacerlo es añadir esto a su modelo:

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

Un modelo de espina dorsal normalmente almacena los valores de datos reales internamente en "model.attributes". Es por eso que cuando pasa su modelo directamente a la plantilla, solo tiene funciones agregadas directamente al modelo y no a ningún dato. Y si usa model.toJSON() normalmente se implementa en la red troncal como _.clone (model.attributes) (vea backbone.js). Entonces tiene los datos y no las funciones agregadas directamente al modelo. Es por eso que lo anterior funciona: usted establece la función en model.attributes, no en el objeto modelo en sí. No haga referencia directamente a model.attributes, use model.get ("calculateColumn") y model.set ("calculateColumn", ...).

So model.get ("calculateColumn") devuelve una función. Si va {{calculateColumn}} en manubrios (suponiendo que esté utilizando manubrios), muestra el valor devuelto por la función. Pero calculateColumn no se enviará al servidor porque la red troncal hace un JSON.stringify a model.toJSON en sincronización (en backbone.js) y JSON.stringify ignora las funciones. Si desea que JSON.stringify no ignore la función (para que la función se convierta en un valor de datos siempre que se ejecute JSON en el modelo, durante la representación de la vista y la sincronización del modelo), anule model.toJSON tal como lo describió @Derick Bailey.

Además, puede derivar su propio modelo base de Backbone.Model e invalidar .toJSON y derivar todos sus modelos de BaseModel si es necesario. Entonces necesitarías una versión genérica de .toJSON que se pueda aplicar a cualquier modelo.

4

Aquí es otra posibilidad: (a partir del modelo de inicialización)

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

Computed properties in Backbone

Cuestiones relacionadas