événements de changement de modèle dans les collections imbriquées ne se déclenchent pas comme prévu

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

  •  14-10-2019
  •  | 
  •  

Question

Je suis en train d'utiliser Backbone.js dans ma première application « réelle » et je besoin d'aide pour le débogage pourquoi certains événements de changement de modèle ne se déclenchent pas comme j'attendre.

Si je crée une collection d'un JSON array à partir du serveur, puis fetch () à des intervalles fixés, je ne suis pas informé si un modèle individuel dans la collection a changé. La documentation backbone suggère que devraient générer de telles notifications. Tout ce que je semble obtenir est une notification de rafraîchissement sur chaque extraction, ce qui est utile. OTOH, si je crée un modèle à partir d'un JSON objet à partir du serveur, puis fetch () le modèle à intervalles fixes, je reçois une notification de changement lorsqu'un change d'attribut. Toutes les idées?

Détails

Mon service Web à l'adresse / employés / {nom d'utilisateur} / tâches renvoie un tableau JSON d'objets de tâche, chaque objet tâche imbriquant un tableau JSON d'objets sous-tâches. Par exemple,

[{
  "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"}
  ]
}]

Un autre service web me permet de changer l'état d'une sous-tâche spécifique dans une tâche spécifique, et se présente comme suit: / tâches / 45002 / sous-tâches / 1 / état / rouge [de côté - je l'intention de changer à un message HTTP services à base, mais l'implémentation actuelle est plus facile pour le débogage]

Je les classes suivantes dans mon application JS:

Modèle et Subtask Collection Subtask

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

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

Modèle de travail avec une instance imbriquée d'une collection sous-tâche

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

Voir la tâche de rend l'élément et écouter les événements de changement du modèle

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

});

Lorsque l'application lance, j'instancier un TaskCollection (en utilisant les données du premier service Web indiqué ci-dessus), se lient à un écouteur pour les événements de changement au TaskCollection, et mettre en place un setTimeout récurrent pour aller chercher () l'instance 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);

...

Tout comme prévu rend la première fois. Mais à ce moment-là, je me attends (ou les deux) un événement de changement Collection ou un événement de changement de modèle pour me faire virer si je change l'état d'une sous-tâche en utilisant mon second service Web, mais cela ne se produit pas.

Drôlement, j'ai eu des événements de changement au feu si j'ai ajouté un supplémentaire niveau d'imbrication, avec le service Web renvoyant un modèle unique, par exemple:

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

Mais cela semble klugey ... et je crains que je ne l'ai pas architecturé mon droit d'application. Je vais ajouter plus de code si elle aide, mais cette question est déjà assez bavard.

Pensées?

Était-ce utile?

La solution

Vous écoutez les événements sur vos tâches, et non pas vos sous-tâches. Si vous voulez que votre tâche d'effectuer les événements pour vos sous-tâches, ainsi que vous devriez faire quelque chose comme ça dans votre 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) });
});

Vous pouvez actualiser les liaisons après un événement de rafraîchissement aussi. De cette façon, quand un événement de changement se produit sur le modèle de sous-tâche, le modèle de tâche déclenchera un modèle de changement aussi bien.

Backbone envoie seulement un événement de rafraîchissement après FETCH vous ne serez pas informé d'un changement dans un modèle spécifique. Regardez la fonction de récupération de collection:

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

Il appellera rafraîchissement par défaut. Voici la fonction de rafraîchissement:

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

Il ajoutera tous les modèles de la collection en mode silencieux (sans événements), puis déclencher un événement rafraîchissement, mais il ne sera pas identifier les éléments modifiés.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top