-1

I create my view with a new collection.

I fire add and sync events :

this.mapDetailsCOllection.on('add', self.onAddElement, self);
this.mapDetailsCOllection.on('sync', self.onSync, self);

Before fetch I do :

this.mapDetailsCOllection.off("add");
this.mapDetailsCOllection.fetch();

And when fetch is ok, in my sync callback :

this.mapDetailsCOllection.on('add', self.onAddElement, self);

But even if I put off the add event I everytime go in add event callback function when I fetch.

Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129
Romain Caron
  • 257
  • 1
  • 3
  • 15

2 Answers2

1

I'm going to suggest the following because I do not have any context on how you've architected your application (Backbone.js is great because it gives you a lot of rope, but how you architect your application can greatly change how you need to implement sync solutions). I'm more than happy to adjust, expand, or clarify this post if you can share a little more about how you've architected your App, View, Collection, and Model code for me to understand what you are trying to achieve.

In your code, I would listen to the update event instead of the add event (since add triggers on each new item added to the collection, compared to update which triggers after any number of items have been added/removed from a collection). Then I would remove the on/off change for add event and instead have your view listen to Collection.reset event rather than turning off and on your listeners for your fetch/sync cycle.

I've used this type of View design-pattern successfully in the past:

var _ = require('lodash');
var DocumentRow = Backbone.View.extend({
  events: {
    "click #someEl": "open"
  },

  clean: function() {
    // cleans up event bindings to prevent memory leaks
  },

  initialize: function(options) {
    _.bindAll(this, [
      'initialize',
      'open',
      'render',
      'clean'
    ]);

    options = options || {};
    this.collection = options.collection ? options.collection : SomeCollection;
    this.listenTo(this.collection, "reset", this.render);
  },

  open: function(item) {
    ...
  },

  render: function() {
    ...
  }

});
Benjamin Dean
  • 1,218
  • 11
  • 11
  • Why `_.bindAll`? `this.listenTo` and `events` callbacks automatically have the view context in this case. `options.collection` is also set to `this.collection` in the constructor, before the initialize. – Emile Bergeron Nov 02 '16 at 17:03
  • Thanks for the guidance Emile. It has been a few years since I've done production app development with Backbone. Those are changes which were not present when I last worked with Backbone. – Benjamin Dean Nov 02 '16 at 17:07
  • 1
    Fair enough, `listenTo` was added Dec. 13, 2012 in v0.9.9 but `events` and the `collection` option were there in 0.1.0. I'm still wondering why `_.bindAll`, maybe if you passed `view.render` as a callback, but here it's not relevant. – Emile Bergeron Nov 02 '16 at 17:16
  • My example is quite simple in nature. I used _.bindAll method to ensure methods defined on the view were accessible and able to be garbage collected. I recommended the clean method to use for destroying event bindings which could occasionally cause application memory leaks when used with sub-views and super-views, back in 2013 when I was still actively developing in BB. When I was using BB, events defined on the view were not automatically bound to the view and were unable to be GC from a super-view or sub-view. – Benjamin Dean Nov 02 '16 at 17:27
  • 1
    The memory leaks mostly happen with `on`, `listenTo` was added to help with that. The custom `clean` function pattern ([like this](https://unspace.ca/dev/2013/avoiding-memory-leaks-in-backbone-js)) is another good practice to ensure everything is unbound. – Emile Bergeron Nov 02 '16 at 17:42
0

Based on this:

The behavior of fetch can be customized by using the available set options. For example, to fetch a collection, getting an "add" event for every new model, and a "change" event for every changed existing model, without removing anything:

collection.fetch({remove: false}) 

collection.set(models, [options]) and this:

All of the appropriate "add", "remove", and "change" events are fired as this happens. Returns the touched models in the collection. If you'd like to customize the behavior, you can disable it with options: {add: false}, {remove: false}, or {merge: false}.

you can pass

collection.fetch({add: false}) 

to avoid firing add event.

user2814599
  • 1,060
  • 1
  • 13
  • 27