Domanda

Sto cercando di utilizzare backbone.js nella mia prima applicazione "reale" e ho bisogno di aiuto debug perché certi eventi di modifica modella non stanno sparando come mi sarei aspettato.

Se creo una collezione da un JSON array dal server, quindi fetch () a intervalli prestabiliti, non vengo avvisato se un singolo modello della collezione è cambiato. La documentazione spina dorsale suggerisce che tali notifiche devono essere generati. Tutto mi sembra di ottenere è una notifica di aggiornamento su ogni fetch, che non è utile. OTOH, se creo un modello da un JSON oggetto dal server, quindi fetch () il modello a intervalli prestabiliti, io capisco una notifica di modifica quando un attributo modifiche. Tutte le idee?

Dettagli

Il mio servizio web / dipendenti / {username} / compiti restituisce una matrice JSON di oggetti dell'attività, con ogni oggetto attività di nidificazione di una serie di oggetti JSON sottoattività. Ad esempio,

[{
  "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 altro servizio web mi permette di cambiare lo stato di una specifica sottoattività in un compito specifico, e si presenta come questo: / attività / 45002 / sottocompiti / 1 / Stato / Red [a parte - ho intenzione di cambiare questo ad un HTTP Post service-based, ma l'implementazione corrente è più facile per il debug]

Ho le seguenti classi nel mio JS app:

Sottoattività modello e Subtask Collection

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

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

Task Modello con un'istanza nidificata di una collezione Sottoattività

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

Task Vista rende la voce e ascoltare per eventi di modifica al modello

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

});

Quando i lanci app, ho un'istanza di un TaskCollection (utilizzando i dati dal primo servizio web di cui sopra), si legano un listener per eventi di modifica al TaskCollection, e impostare un setTimeout ricorrenti per andare a prendere () l'istanza 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);

...

Tutto rende come previsto la prima volta. Ma a questo punto, mi sarei aspettato uno (o entrambi) un cambiamento raccolta eventi o di un evento di modifica modello per ottenere licenziato se cambio lo stato di un'attività secondaria usando il mio secondo servizio web, ma questo non accade.

È buffo, ho avuto gli eventi di modifica al fuoco se ho aggiunto un ulteriore livello di nidificazione, con il servizio web che restituisce un unico modello, ad esempio:

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

Ma questo sembra klugey ... e ho paura che non ho architettato la mia applicazione giusta. Io includo più di codice se aiuta, ma questa domanda è già piuttosto prolisso.

Pensieri?

È stato utile?

Soluzione

State ascoltando gli eventi sui vostri compiti, non le attività secondarie. Se volete che il vostro compito di portare gli eventi per le attività secondarie così si dovrebbe fare qualcosa di simile nel tuo 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) });
});

Si potrebbe desiderare di aggiornare le associazioni dopo un evento di aggiornamento anche. In questo modo quando si verifica un evento di modifica sul modello sottoattività, il modello compito attiverà un modello di cambiamento pure.

Backbone invierà solo un evento di aggiornamento dopo un'operazione di recupero non sarà informato di un cambiamento di un modello specifico. Guardate la funzione di recupero della raccolta:

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

Si chiamerà aggiornamento per impostazione predefinita. Ecco la funzione di aggiornamento:

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

Si aggiungerà tutti i modelli della collezione silenziosamente (senza eventi) e quindi innescare un evento di aggiornamento, ma non sarà identificare gli elementi modificati.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top