开发者

How do I replace a model in a Backbone.Collection?

Suppose I have a Backbone.Collection with three models. I want to replace the middle one, keeping the first and third models in their current positions. (Assume ther开发者_运维知识库e's no comparator.) How do I do this?


This is a good question and still relevant today, so it's worth answering.

It is possible the functionality used in my answer did not exist when you asked the question, but it is now quite straightforward to do this.

Anyway, lets assume your collection is named myCollection and already has 3 models stored in it. Lets also say you have a new model named newModel that you want use to replace the existing middle model in the collection. To replace the middle model, leaving the first and third models untouched, you can do this:

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

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

This will do exactly what you want and raise the remove event for the model removed and the add event for the replacement, which is what you wanted also.


There is a simple mechanism built into Backbone that handles this issue

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


You could introduce a replaceAt function in the backbone collection that would look something like this:

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

Its based on the _add and _remove methods. It should fire the appropriate events that you are looking for but I didn't test for that. I tested that it would replace an element in the collection at the appropriate place.

(using backbone .3.3)


One approach is to modify the collection.models array directly, then call

collection.refresh(collection.models)

However, this will invoke an add event listing every model. Ideally, I'd want to invoke a remove event for the model that's removed and an add event for the new one. I'm not sure whether that's possible without using a comparator and adding indices on my models...


Although of this question asked a lot of time ago, it relevant even for today.
And actually its very easy.

  1. we need to get the old model index inside the collection.
  2. and then add the new one into the collection at the same index position and merge

look in the example below:

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

Hope it would help somone ...
good luck !

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜