2011-01-01 9 views
9

Intento utilizar backbone.js en mi primera aplicación "real" y necesito ayuda para depurar por qué ciertos eventos de cambio de modelo no se activan como era de esperar.Eventos de cambio de modelo en colecciones anidadas que no se activaron como se esperaba

Si creo una colección desde un arreglo JSON del servidor, y luego la obtengo() en intervalos establecidos, no me notifican si un modelo individual en la colección ha cambiado. La documentación de la red troncal sugiere que tales notificaciones deberían ser generadas. Todo lo que parece obtener es una notificación de actualización en cada búsqueda, que no es útil. OTOH, si creo un modelo de un objeto JSON del servidor, entonces obtengo() el modelo a intervalos establecidos, obtengo una notificación de cambio cuando cambia un atributo. ¿Algunas ideas?

detalles

Mi servicio web en/empleados/{nombre de usuario}/tareas devuelve una matriz JSON de objetos de la tarea, la tarea de cada objeto que anidan una matriz de objetos JSON subtarea. Por ejemplo,

[{ 
    "id":45002, 
    "name":"Open Dining Room", 
    "subtasks":[ 
    {"id":1,"status":"YELLOW","name":"Clean all tables"}, 
    {"id":2,"status":"RED","name":"Clean main floor"}, 
    {"id":3,"status":"RED","name":"Stock condiments"}, 
    {"id":4,"status":"YELLOW","name":"Check/replenish trays"} 
    ] 
},{ 
    "id":47003, 
    "name":"Open Registers", 
    "subtasks":[ 
    {"id":1,"status":"YELLOW","name":"Turn on all terminals"}, 
    {"id":2,"status":"YELLOW","name":"Balance out cash trays"}, 
    {"id":3,"status":"YELLOW","name":"Check in promo codes"}, 
    {"id":4,"status":"YELLOW","name":"Check register promo placards"} 
    ] 
}] 

Otro servicio web me permite cambiar el estado de una subtarea específica en una tarea específica, y se parece a esto:/tareas/45002/subtareas/1/estado/rojo [a un lado - que pretendo para cambiar a un servicio basado en HTTP post, pero la implementación actual es más fácil para la depuración]

tengo las siguientes clases en mi aplicación JS:

Subtarea modelo y Subtarea Colección

var Subtask = Backbone.Model.extend({}); 

var SubtaskCollection = Backbone.Collection.extend({ 
    model: Subtask 
}); 

modelo de tarea con una instancia anidada de una colección Subtarea

var Task = Backbone.Model.extend({ 
    initialize: function() { 

    // each Task has a reference to a collection of Subtasks 
    this.subtasks = new SubtaskCollection(this.get("subtasks")); 

    // status of each Task is based on the status of its Subtasks 
    this.update_status(); 

    }, 
    ... 
}); 

var TaskCollection = Backbone.Collection.extend({ 
    model: Task 
}); 

vista de tareas que hace que el elemento y escuchar los sucesos de cambio al modelo

var TaskView = Backbone.View.extend({ 

    tagName: "li", 

    template: $("#TaskTemplate").template(), 

    initialize: function() { 
    _.bindAll(this, "on_change", "render"); 
    this.model.bind("change", this.on_change); 
    }, 

    ... 

    on_change: function(e) { 
    alert("task model changed!"); 
    } 

}); 

Cuando se inicie la aplicación, Instalo una TaskCollection (usando los datos del primer servicio web enumerado anteriormente), ato un oyente para cambios de eventos a TaskCollection, y configuré un setTimeout recurrente para obtener() el TaskCollecti en instancia.

... 

TASKS = new TaskCollection(); 

TASKS.url = ".../employees/" + username + "/tasks" 

TASKS.fetch({ 
    success: function() { 
    APP.renderViews(); 
    } 
}); 


TASKS.bind("change", function() { 
    alert("collection changed!"); 
    APP.renderViews(); 
}); 


// Poll every 5 seconds to keep the models up-to-date. 
setInterval(function() { 
    TASKS.fetch(); 
}, 5000); 

... 

Todo se renueva como se esperaba la primera vez. Pero en este punto, esperaría que cualquiera (o ambos) un evento de cambio de Colección o un evento de cambio de Modelo se dispare si cambio el estado de una subtarea usando mi segundo servicio web, pero esto no sucede.

Curiosamente, me hizo llegar a los eventos de cambio de incendio si he añadido una nivel adicional de anidación, con el servicio web que devuelve un único modelo, por ejemplo:

"employee":"pkaushik", "tasks":[{"id":45002,"subtasks":[{"id":1..... 

pero esto parece klugey ... y me temo que no he diseñado bien mi aplicación. Incluiré más código si ayuda, pero esta pregunta ya es bastante detallada.

¿Pensamientos?

Respuesta

8

Está escuchando los eventos de sus tareas, no sus tareas secundarias. Si desea que su tarea de llevar a los eventos para sus subtareas, así que debe hacer algo como esto en su Task.initialize:

var self = this;  
this.subtasks.bind("refresh", function(){ self.trigger("refresh:subtask")}); 
this.subtasks.each(function(st){ 
    st.bind("change", function(){ self.trigger("change:subtask:" + st.id, st) }); 
}); 

Es posible que desee actualizar los enlaces después de un evento de actualización también. De esta forma, cuando se produce un evento de cambio en el modelo de subtarea, el modelo de tarea activará también un modelo de cambio.

Backbone solo enviará un evento de actualización después de una búsqueda, no se le informará de un cambio en un modelo específico. Mire la función de búsqueda de la colección:

options.success = function(resp) { 
    collection[options.add ? 'add' : 'refresh'](collection.parse(resp), options); 
    if (success) success(collection, resp); 
}; 

Llamará a la actualización de forma predeterminada. Aquí está la función de actualización:

refresh : function(models, options) { 
    models || (models = []); 
    options || (options = {}); 
    this.each(this._removeReference); 
    this._reset(); 
    this.add(models, {silent: true}); 
    if (!options.silent) this.trigger('refresh', this, options); 
    return this; 
} 

que se sumará a todos los modelos de la colección silenciosa (sin eventos) y luego desencadenar un evento de actualización, pero no va a identificar los elementos modificados.

+0

¡Gracias por responder! Agregué manipuladores de eventos de cambio a cada modelo de la colección como sugirió, pero desafortunadamente eso no ayuda. He editado la publicación original para describir mejor el problema que estoy enfrentando (ver el segundo párrafo). En cuanto a su comentario sobre escuchar cambios en las subtareas, no veo por qué eso debería importar desde la perspectiva del evento, "subtareas" es un atributo del modelo de Tarea, que acabo de convertir en una colección anidada. Mi problema parece ser más simple de lo que había pensado originalmente: simplemente no recibo notificaciones de cambio a los modelos de una colección. –

+0

He actualizado mi respuesta – Julien

+0

Buenas cosas, Julien: realmente disfruto sus respuestas a las cosas relacionadas con Backbone en SO – ambertch

Cuestiones relacionadas