eventos de cambio de modelo en colecciones anidadas no se activa como se esperaba

StackOverflow https://stackoverflow.com/questions/4576150

  •  14-10-2019
  •  | 
  •  

Pregunta

Estoy intentando utilizar Backbone.js en mi primera aplicación "real" y necesito un poco de ayuda de depuración por qué ciertos eventos de cambio de modelo no están disparando lo que cabe esperar.

Si creo una colección de un JSON array desde el servidor, a continuación, fetch () que a intervalos fijos, no recibo notificado si un modelo individual de la colección ha cambiado. La documentación espina dorsal sugiere que tales notificaciones se deben generar. Todo lo que parece a conseguir es una notificación de actualización en cada búsqueda, que no es útil. Otoh, si creo un modelo de un JSON objetos desde el servidor, a continuación, fetch () el modelo a intervalos fijos, hago llegar una notificación de cambio cuando un atributo cambios. 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 es similar al siguiente: / tareas / 45002 / subtareas / 1 / estado / rojo [aparte - Tengo la intención de cambiar a un HTTP POST servicio basado, pero la implementación actual es más fácil para depurar]

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

Tarea Modelo 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 en el 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 los lanzamientos de aplicaciones, que una instancia de un TaskCollection (usando los datos de la primera servicio web que aparece más arriba), se unen a un oyente para eventos de cambio a la TaskCollection, y establecieron un setTimeout recurrentes a fetch () la instancia TaskCollection.

...

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 lo hace como se espera la primera vez. Pero en este punto, yo esperaría uno (o ambos) un evento de cambio de colección o un evento de cambio de modelo que son despedidos si cambio de 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 un adicional del nivel 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 architected mi aplicación correcta. Voy a incluir más código si ayuda, pero esta cuestión ya es bastante detallado.

Los pensamientos?

¿Fue útil?

Solución

Usted está escuchando a los eventos en 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 manera, cuando se produce un evento de cambio en el modelo de subtarea, el modelo de tarea se disparará un modelo de cambio también.

El soporte estructural sólo enviará un evento de actualización después de una zona de alcance no será informado de un cambio en un modelo específico. Vistazo a la función de captación de la colección:

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

Se llamará actualización por defecto. Esta es 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;
}

Se añadirá 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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top