Alexander Mills
Alexander Mills

Reputation: 100220

Backbone - distinguish between change due to fetch and change from front-end

Is there a good pattern for Backbone in order to distinguish change events that are a result from a server fetch versus change events that are due to the front-end events?

       this.on('change',function(model){
                self.needsPersisting = true;
          });

For example: if the change is the result of the server, I don't wish to set the needsPersisting flag to true, but if the change is a result of the front-end I do wish to set the needsPersisting flag to true.

Upvotes: 0

Views: 92

Answers (2)

Neha
Neha

Reputation: 11

There can be multiple solutions for this issue. You can pick your solution based on your requirement:

1. Distinguish based on variable name :

There is a parse function in Backbone (both model and collection have that function) which is called whenever the model/collection is returned by the server. We can override that function and set the variable before returning the response.

parse: function(response){
    // Setting variable value
    this.changedByServer = true;
    // Returning response as this will be mapped to model/collection
    return response;
}

2. Distinguish based on event

This approach is useful in cases where resetting model/collection after server fetch is acceptable. We can fetch the model with option "reset:true" and it will trigger "reset" event when the model gets fetched from server.

modelObj.fetch({reset: true});

modelObj.on('reset', function(){
    // This handler is called when model gets fetched from server
});

Upvotes: 1

Alexander Mills
Alexander Mills

Reputation: 100220

If you look at the annotated source for Backbone, there is a fetch method for a model:

fetch: function(options) {
  options = _.extend({parse: true}, options);
  var model = this;
  var success = options.success;
  options.success = function(resp) {
    var serverAttrs = options.parse ? model.parse(resp, options) : resp;
    if (!model.set(serverAttrs, options)) return false;
    if (success) success.call(options.context, model, resp, options);
    model.trigger('sync', model, resp, options);
  };
  wrapError(this, options);
  return this.sync('read', this, options);
},

from what I can tell, a 'sync' event is fired not only when this model is sync but also any collection that contains the model.

so the I way I seem to have solved it, is to deal with the fact that a 'change' event is fired when the server attributes are set, by knowing that the 'sync' event will fire afterwards, which will overwrite the boolean flag that I have for persisting a model, so this seems to work:

         var BaseModel = Backbone.Model.extend({

                needsPersisting: false,

                constructor: function () {
                    var self = this;
                    this.on('change',function(model,something){
                        self.needsPersisting = true; //fired when attributes are changed, regardless over whether from server or client
                    });
                    this.on('sync',function(){
                        self.needsPersisting = false; //sync event is fired on fetch after the change event is fired in the source
                    });
                    Backbone.Model.apply(this, arguments);
                }

           });

Upvotes: 0

Related Questions