Backbone.Collection.merge ([opciones])
Edificio en @ respuesta de Jeb anterior, he encapsula este comportamiento en una extensión principal que se puede copiar y pegar en un archivo .js archivar e incluir en su página (después de incluir la biblioteca Backbone en sí).
Proporciona un método llamado merge
para objetos Backbone.Collection. En lugar de reiniciar por completo la colección existente (como lo hace fetch
), compara la respuesta del servidor a la colección existente y combina sus diferencias.
- Se añade modelos que se encuentran en la respuesta, pero no en la colección existente.
- Es elimina modelos que están en la colección existente, pero no en la respuesta.
- Finalmente, actualiza los atributos de los modelos encontrados en la colección existente Y en la respuesta.
eventos Todos los esperados se activan para añadir, eliminar y actualizar los modelos.
El opciones hash tienen success
error
y devoluciones de llamada que se pasará (collection, response)
como argumentos, y proporciona una tercera opción de devolución de llamada llama complete
que se ejecuta independientemente del éxito o error (sobre todo útil para los escenarios de votación).
Activa eventos llamados "merge: success" y "merge: error".
Aquí es la extensión:
// 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 uso Escenario:
var MyCollection = Backbone.Collection.extend({
...
});
var collection = new MyCollection();
collection.merge();
Manejo de errores Uso Escenario:
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";
}
};
solución excelente. Estaba tratando de lograr esto dentro del método collection.parse y llegar a ninguna parte. Realmente espero que este comportamiento se agregue a la API de Backbone. De todos modos, aquí está mi implementación del ítem TODO para actualizar los modelos existentes. '_ (collection.models) .Cada (función (actividad) { \t \t \t \t \t \t si (newModelIds.indexOf (activity.id)! = -1) {actividad \t \t \t \t \t \t \t. conjunto (newCollection.get (activity.id)); \t \t \t \t \t \t} \t \t \t \t \t}, eso); ' –