DasBoot
DasBoot

Reputation: 479

backbonejs model.set, trigger event on any case

Is there a way to force change:attribute event to trigger with model.set() even if attribute data havent changed?

model.set('attribute', 2); // will trigger the change:attribute event
model.set('attribute', 2); // will not trigger again since the value has not changed

So again, is there a way to trigger second set even if the value havent changed? Thanks for your time.

Upvotes: 0

Views: 916

Answers (2)

Peter Wagener
Peter Wagener

Reputation: 2092

Not without overriding Backbone.Model.set(...). I've never needed this functionality... the "only fire an event when it changes" design encourages best practices in event propagation I think. But you could just provide a method that silently removes the value then immediately sets it again.

Edit: Per mu is too short's comment below, you also need to handle the possibility of setLoudly being given a hash of attributes. Thus the need for the clearSilently method which handles both individual attributes as well as hashes:

var MyModel = Backbone.Model.extend({
    setLoudly: function(attr, value, options) {
        this.unset(attr, { silent: true });
        return Backbone.Model.prototype.set.call(this, attr, value, options);
    },

    clearSilently: function(attr) {
        if (_.isString(attr)) {
            this.unset(attr, { silent: true });
        } else {
            _.each(_.keys(attr), function(key) {
                this.unset(key, { silent: true });
            }, this);
        }
    }
});

var myModel = new MyModel({
   foo: "bar",
   baz: 4
});

myModel.set('foo', 'bar');  // <<=== No Event
myModel.setLoudly('foo', 'bar');  // <<=== One 'change change:foo' event
myModel.set({
    foo: "bar",
    baz: 4
});  // <<=== No Events
myModel.setLoudly({
    foo: "bar",
    baz: 4
});   // <<=== Will receive 'change change:foo change:baz'

If you want to always use that method when setting data, just name it set instead of setLoudly and you should be good. YMMV.

Upvotes: 3

Timo
Timo

Reputation: 369

When setting an attribute on a Model, Backbone will basically check if the new attribute is different from the current one and then trigger the change event. There is no option to override this behavior. You can try one of the following:

  1. Change your Backbone source to override this behavior - remove the check. (not recommended)
  2. Override the Backbone.Model.set(...) like Peter Wagener suggested.
  3. Trigger the change event manually:

    model.set('attribute', 2, {silent:true}); //Pass silent to prevent 2 change events if the attribute actually changed.
    model.trigger('change');
    

Upvotes: 1

Related Questions