web-dev-qa-db-fra.com

Backbone.js: l'événement "changement" de la collection ne se déclenche pas

J'ai une collection assez simple, mais je n'arrive pas à me lier à son événement de changement. Dans la console de Chrome, je lance:

var c = new AwesomeCollection();
c.bind("change", function(){
  console.log('Collection has changed.');
});

c.add({testModel: "Test"}); // Shouldn't this trigger the above log statement?

Étant donné que c'est une de ces choses qui peut être difficile à retrouver, je doute que quiconque sache du haut de la tête ce qui se passe (si c'est le cas, super!). Je pose donc deux questions:

  1. Le code ci-dessus devrait-il fonctionner comme prévu?
  2. Dans l'affirmative, avez-vous des suggestions sur la façon de déterminer où cela échouerait?

Merci

40
Thomas

L'événement change n'est déclenché que lorsque l'un des modèles des collections est modifié. Lorsqu'un modèle est ajouté à la collection, l'événement add est déclenché.
Voir Backbone.js ' Collection Documentation :

Vous pouvez lier des événements "changer" pour être averti lorsqu'un modèle de la collection a été modifié, écouter les événements "ajouter" et "supprimer" [...]

Pour écouter lorsqu'un add se produit, modifiez votre code pour qu'il soit

var c = new AwesomeCollection();
c.bind("add", function(){
  console.log('Collection has changed.');
});

c.add({testModel: "Test"}); 
68
soldier.moth

Non, cela ne fait que déclencher l'événement "add". Cela déclenchera l'événement de changement si vous procédez comme suit:

var c = new AwesomeCollection();
c.bind("change", function() {
  console.log('Collection has changed.');
});

var model = new Backbone.Model({testModel: "Test"});
c.add(model);
model.set({testModel: "ChangedTest"});
11
timDunham

Si vous voulez savoir quand quelque chose d'important a été fait avec une collection, ce sont les événements que vous voulez probablement écouter: change add remove reset

En ce qui concerne votre exemple, voici à quoi pourrait ressembler votre code:

var c = new AwesomeCollection();
c.bind('change add remove reset', function(){
    console.log('Collection has changed.');
});
10
Chris Dutrow

Cela peut ne pas être nécessaire dans la plupart des cas, mais vous pouvez déclencher manuellement un événement de modification sur votre objet/collection:

object.trigger("change");
5
Chicowitz

Je ne le trouve documenté nulle part, mais l'événement "tous" se déclenche sur toutes les actions, y compris l'ajout, la suppression et la modification.

var c = new AwesomeCollection();
c.bind("all", function(){
  console.log('Something happened');
});

c.add({testModel: "Test"}); 
1
Gaurav Gupta

J'espère que AwesomeCollection est un BackboneCollection.

var AwesomeCollection = new Backbone.Collection();

AwesomeCollection.bind('add', function() {
    console.log('new object in the collection');
});

AwesomeCollection.add({something});

Cela devrait déclencher votre événement. Sinon, il y a un autre problème ailleurs.

Modifier: le changement ne peut pas être déclenché lors de l'ajout d'un événement comme d'autres l'ont dit.

0
malletjo

J'ai rencontré le même problème que le vôtre sur le backbone 0.5.3.

En regardant l'implémentation de Backbone.Collection.reset () (qui est appelée après un fetch () si vous ne fournissez aucune propriété facultative "add"), ligne 503 à 511:

// When you have more items than you want to add or remove individually,
// you can reset the entire set with a new list of models, without firing
// any `added` or `removed` events. Fires `reset` when finished.
reset : function(models, options) {
  models  || (models = []);
  options || (options = {});
  this.each(this._removeReference);
  this._reset();
  this.add(models, {silent: true});
  if (!options.silent) this.trigger('reset', this, options);
  return this;
},

2 choses sont importantes ici:

  this.add(models, {silent: true});

ce qui signifie qu'aucun événement "add" ne sera déclenché.

La deuxième chose est la:

  if (!options.silent) this.trigger('reset', this, options);

Cela signifie que si vous remplacez votre code par:

var c = new AwesomeCollection();
c.bind("reset", function(){
  console.log('Collection has changed.');
}

c.add({testModel: "Test"}); // Shouldn't this trigger the above log statement?

Ça devrait marcher (ça a marché pour moi)

0
Frédéric

De plus, nous ne pouvons pas le dire à partir de votre exemple, mais une collection doit avoir sa propriété de modèle définie si vous voulez lui ajouter des modèles en passant simplement un objet. Sinon, vous devez passer une instance de modèle pour ajouter ().

0
maxl0rd