3

I want to increment the model position attribute everytime a new model is added to the collection, I've tried converting defaults to be a function that returns a position equalled to ++collection with no success. Can anyone advise the best approach to do this?

var Col = Backbone.Collection.extend()
var Mod = Backbone.Model.extend({
    defaults() {
        return {
            position: ++this.collection.length
        }
    }
})
var col = new Col([{
    id: 1
}, {
    id: 2
}])

col.toJSON() // returns [{id: 1}, {id: 2}]
styler
  • 15,779
  • 23
  • 81
  • 135
  • Possible duplicate of [How to set Backbone model's defaults based on collection attribute](https://stackoverflow.com/questions/13232904/how-to-set-backbone-models-defaults-based-on-collection-attribute) – Emile Bergeron Nov 29 '17 at 17:04
  • Specifically [my answer](https://stackoverflow.com/a/40476079/1218980) on that question. Don't override `create`, `add`, etc. like most other answers are saying. – Emile Bergeron Nov 29 '17 at 17:06
  • So I could jut use the add event on the collection to set the position that way? Not sure what you are achieving a newModel method? – styler Nov 29 '17 at 18:03
  • The point is to override (hook) `_prepareModel` and do what you want from there. In my answer, I simplified this process by making a base collection which adds a custom `onNewModel` handler function, but you could even trigger your own event on the collection, etc. – Emile Bergeron Nov 29 '17 at 18:08

1 Answers1

2

You've got 2 distinct problems.

  1. Set Backbone model's defaults based on a collection attribute
    but if it's only for the position, this may not be necessary.
  2. Keeping track of the position of a model inside a collection.

Using the collection's length is not enough to precisely keep track of the position.

Imagine you have 3 models, the first model is at position 1 and the last model at position 3. Then the first two models are removed and a new model is added at the end, with the collection length now being 2, you'll have incoherent positions already.

You'd need to update the position of all the models in the collection each time there's a change in the collection.

Here's a simple example using the update event.

var PositionCol = Backbone.Collection.extend({
    initialize: function(models, options) {
        this.listenTo(this, 'update', this.updatePositions);
    },
    updatePositions: function(options) {
        this.each(function(model, index) {
            model.set({ position: index });
        }, this);
    },
});
Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129
  • 1
    Yeah this makes sense!! I noticed that my model positions were out of sync usnig the collection length, I've gone with adding in the update event listener and making the position update which works nicely. Thanks! – styler Nov 30 '17 at 08:48