2011-06-06 7 views

Respuesta

18

Esta es una buena pregunta y siempre de actualidad, por lo que vale la pena responder.

Es posible que la funcionalidad utilizada en mi respuesta no existiera cuando hizo la pregunta, pero ahora es bastante sencillo hacerlo.

De todos modos, supongamos que su colección se llama myCollection y ya tiene 3 modelos almacenados en ella. Digamos también que tiene un nuevo modelo llamado newModel que desea usar para reemplazar el modelo medio existente en la colección. Para reemplazar el modelo de media, dejando el primer y tercer modelos sin tocar, se puede hacer esto:

myCollection.remove(myCollection.at(1)); 

myCollection.add(newModel, {at: 1}); 

Esto va a hacer exactamente lo que quiere y provocar el evento remove para el modelo eliminado y el evento add para la sustitución, que es lo que querías también.

0

Un método consiste en modificar la matriz collection.models directamente, a continuación, llamar

collection.refresh(collection.models) 

Sin embargo, esto va a invocar un evento add lista de los modelos. Idealmente, me gustaría invocar un evento remove para el modelo que se eliminó y un evento add para el nuevo. No estoy seguro de si eso es posible sin utilizar un comparator y la adición de índices en mis modelos ...

2

Se podría introducir una función replaceAt en la colección columna vertebral que sería algo como esto:

replaceAt : function(model, options, replaceIndex) { 
     this._replaceAt(model, options, replaceIndex); 
     return this; 
    }, 

    _replaceAt : function(model, options, replaceIndex) { 

     options || (options = {}); 
     if (!(model instanceof Backbone.Model)) { 
     model = new this.model(model, {collection: this}); 
     } 
     var already = this.getByCid(model); 
     if (already) throw new Error(["Can't add the same model to a set twice", already.id]); 
     this._byId[model.id] = model; 
     this._byCid[model.cid] = model; 
     model.collection = this; 
     replacedModel = this.at(replaceIndex) 
     this.models.splice(replaceIndex, 1, model); 
     this._cleanModel(replacedModel, options); 
     model.bind('all', this._boundOnModelEvent); 
     if (!options.silent) model.trigger('add', model, this, options); 
     return model; 
    }, 

    _cleanModel : function (model, options) { 
     if(!model) return null; 
     delete this._byId[model.id]; 
     delete this._byCid[model.cid]; 
     delete model.collection; 
     if(!options.silent) model.trigger('remove', model, this, options); 
     model.unbind('all', this._boundOnModelEvent); 
     return model; 
    }, 

Su basado en los métodos _add y _remove. Debería activar los eventos apropiados que está buscando, pero no hice la prueba para eso. Probé que reemplazaría un elemento en la colección en el lugar apropiado.

(utilizar una estructura básica .3.3)

+0

Hmm, así que tal vez debería escribir una subclase 'LinearCollection' para mi propósito. –

0

Aunque de esta pregunta hace mucho tiempo, es relevante incluso para hoy.
Y en realidad es muy fácil.

  1. tenemos que obtener el viejo índice de modelo dentro de la colección.
  2. y luego añadir el nuevo en la colección en la misma posición de índice y combinar

mirada en el siguiente ejemplo:

var index = collection.indexOf(oldModel); //1 
collection.add(newModel, {at: index, merge: true}); //2 

espero que ayudaría somone ...
buena suerte !

+1

No creo que esto sea correcto. Usado con 'collection.set',' merge: true' toma los atributos del nuevo modelo y 'establece's en el modelo existente en el índice objetivo. Usado con 'collection.add', no tiene ningún efecto (al menos en Backbone 1.1.0). –

+1

Hola Trevor, tuve esta conversación con un amigo y le indiqué este enlace: [backbone add collection] (http://backbonejs.org/#Collection-add) en el sitio oficial de backbone. y por cierto probé el código anterior y su funcionamiento. De todos modos, gracias por los comentarios. –

5

Hay un mecanismo simple integrado en la espina dorsal que se ocupa de este problema

myCollection.add(newModel, {merge: true});

+0

Esta debería ser la respuesta aceptada. –

+1

Fusionar y reemplazar son comportamientos diferentes. El OP preguntó cómo reemplazar. Sin embargo, estoy de acuerdo en que esta respuesta es informativa y aborda otra necesidad. Upvoted. – dcarson

+2

No estoy de acuerdo. OP hizo una pregunta específica que esta respuesta no aborda. Además, la respuesta no especifica que no aborda la pregunta original de OP. Podría confundir a otros lectores. Sería una gran respuesta para una pregunta diferente. Downvoted. –

Cuestiones relacionadas