styler
styler

Reputation: 16501

Prevent model set `change` event when clearing model and resetting to defaults?

I am setting a model on submission of a contact form so I'm grabbing all of the input values, creating an object literal then setting this on the model. I have a change event listener that then outputs a summary screen. I also have a reset button that clears the model and resets the model to the defaults. My problem is that this reset also triggers the change event which then displays the summary screen, which I don't want. Is it possible to prevent this?

Examples of my Backbone View

initialize: function() {
        console.log('ContactForm::initialize');

        this.listenTo(this.model, 'invalid', this.onModelInvalid);
        this.listenTo(this.model, 'change', this.onModelSet);
    },
onFormSubmit: function(event) {

        event.preventDefault();

        var inputs = this.el.querySelectorAll('.js-input');

        this.setModelData(inputs);
    },

    setModelData: function(elements) {

        var attributes = {};

        for (var i = 0, len = elements.length; i < len; i++) {

            var thisInput = elements[i],
                thisInputValue = thisInput.value;

            attributes[thisInput.id] = thisInputValue;
        }

        this.model.set(attributes, { validate: true });
    },

    /*
     *  this.model returned, this model will contain an array of validation errors accessed via this.model.validationError
     *  loop through these and output each error field.
     */
    onModelInvalid: function() {
        console.log('ContactForm::onModelInvalid', this.model.validationError);

        this.toggleValidationClass('add');
    },

    onModelSet: function() {
        console.log('ContactForm::onModelSet', this.model.toJSON());

        Backbone.Events.trigger('show:summary', this.model);
    },

    onFormReset: function(event) {

        event.preventDefault();

        // Reset the model to default
        this.model.clear().set(this.model.defaults);

        // Reset form fields
        this.$('.js-form')[0].reset();

        // Remove all invalid classes if errors exist
        if(this.model.validationError && this.model.validationError.length > 0) {
            this.toggleValidationClass('remove');
        }

        console.log(this.model.toJSON());
    }

Upvotes: 1

Views: 97

Answers (2)

ivarni
ivarni

Reputation: 17878

There's an (undocumented by .set) option called silent

(For some reason, the docs for .clear mentions it though).

Relevant source on github: https://github.com/jashkenas/backbone/blob/master/backbone.js#L482

So try

this.model.clear({silent:true}).set(this.model.defaults, {silent:true});

Demonstration on plnkr using the following code

var model = new Backbone.Model();

model.on('change', function(e) {
  document.write(JSON.stringify(e.changed));
});

model.set('foo', 'bar'); 
model.clear({silent: true}).set('foo', 'bar', {silent: true});
model.set('test', '123');

Running this writes {"foo":"bar"}{"test":"123"} to the document, so the line where {silent:true} was passed to .clear() and .set() did not generate any change-events.

Upvotes: 5

JNF
JNF

Reputation: 3730

Use an attribute on the model to tell if it's newly loaded or being reset. Set it to true in onFormReset and test for it in onModelSet.

Upvotes: 0

Related Questions