Backbone.Collection.merge ([options])
bâtiment sur @ réponse de Jeb ci-dessus, je l'ai encapsulé ce comportement dans une extension de réseau fédérateur que vous pouvez copier et coller dans un .js fichier et inclure dans votre page (après avoir inclus la bibliothèque Backbone elle-même).
Il fournit une méthode appelée merge
pour les objets Backbone.Collection. Plutôt que de réinitialiser complètement la collection existante (comme le fait fetch
), elle compare la réponse du serveur à la collection existante et fusionne leurs différences.
- Il ajoute modèles qui sont dans la réponse, mais pas dans la collection existante.
- Il supprime les modèles qui sont dans la collection existante, mais pas dans la réponse.
- Enfin, il met à jour les attributs des modèles trouvés dans la collection existante ET dans la réponse.
Tous les événements attendus sont déclenchés pour l'ajout, la suppression et la mise à jour de modèles.
Le hachage options prend success
et error
callbacks qui seront transmis (collection, response)
comme arguments, et il fournit une troisième option de rappel appelée complete
qui est exécuté indépendamment de la réussite ou l'erreur (surtout utile pour les scénarios de vote).
Il déclenche les événements appelés "fusionner: succès" et "fusionner: erreur".
Voici l'extension:
// Backbone Collection Extensions
// ---------------
// Extend the Collection type with a "merge" method to update a collection
// of models without doing a full reset.
Backbone.Collection.prototype.merge = function(callbacks) {
// Make a new collection of the type of the parameter
// collection.
var me = this;
var newCollection = new me.constructor(me.models, me.options);
this.success = function() { };
this.error = function() { };
this.complete = function() { };
// Set up any callbacks that were provided
if(callbacks != undefined) {
if(callbacks.success != undefined) {
me.success = callbacks.success;
}
if(callbacks.error != undefined) {
me.error = callbacks.error;
}
if(callbacks.complete != undefined) {
me.complete = callbacks.complete;
}
}
// Assign it the model and url of collection.
newCollection.url = me.url;
newCollection.model = me.model;
// Call fetch on the new collection.
return newCollection.fetch({
success: function(model, response) {
// Calc the deltas between the new and original collections.
var modelIds = me.getIdsOfModels(me.models);
var newModelIds = me.getIdsOfModels(newCollection.models);
// If an activity is found in the new collection that isn't in
// the existing one, then add it to the existing collection.
_(newCollection.models).each(function(activity) {
if (_.indexOf(modelIds, activity.id) == -1) {
me.add(activity);
}
}, me);
// If an activity in the existing collection isn't found in the
// new one, remove it from the existing collection.
var modelsToBeRemoved = new Array();
_(me.models).each(function(activity) {
if (_.indexOf(newModelIds, activity.id) == -1) {
modelsToBeRemoved.push(activity);
}
}, me);
if(modelsToBeRemoved.length > 0) {
for(var i in modelsToBeRemoved) {
me.remove(modelsToBeRemoved[i]);
}
}
// If an activity in the existing collection is found in the
// new one, update the existing collection.
_(me.models).each(function(activity) {
if (_.indexOf(newModelIds, activity.id) != -1) {
activity.set(newCollection.get(activity.id));
}
}, me);
me.trigger("merge:success");
me.success(model, response);
me.complete();
},
error: function(model, response) {
me.trigger("merge:error");
me.error(model, response);
me.complete();
}
});
};
Backbone.Collection.prototype.getIdsOfModels = function(models) {
return _(models).map(function(model) { return model.id; });
};
simple Scénario d'utilisation:
var MyCollection = Backbone.Collection.extend({
...
});
var collection = new MyCollection();
collection.merge();
Gestion des erreurs Scénario d'utilisation:
var MyCollection = Backbone.Collection.extend({
...
});
var collection = new MyCollection();
var jqXHR = collection.merge({
success: function(model, response) {
console.log("Merge succeeded...");
},
error: function(model, response) {
console.log("Merge failed...");
handleError(response);
},
complete: function() {
console.log("Merge attempt complete...");
}
});
function handleError(jqXHR) {
console.log(jqXHR.statusText);
// Direct the user to the login page if the session expires
if(jqXHR.statusText == 'Unauthorized') {
window.location.href = "/login";
}
};
solution excellente. J'essayais d'accomplir ceci dans la méthode de collection.parse et n'obtenant nulle part. J'espère vraiment que ce comportement est ajouté à l'API de Backbone. Quoi qu'il en soit, voici ma mise en œuvre de l'article TODO pour la mise à jour des modèles existants. '_ (collection.models) .Chaque (fonction (activité) { \t \t \t \t \t \t si (newModelIds.indexOf (activity.id)! = -1) { \t \t \t \t \t \t activité \t. set (newCollection.get (activity.id)); \t \t \t \t \t \t} \t \t \t \t \t}, que); ' –