Backbone.js Model validation fails to prevent Model from saving

Posted by Benjen on Stack Overflow See other posts from Stack Overflow or by Benjen
Published on 2012-06-21T03:07:32Z Indexed on 2012/06/21 3:16 UTC
Read the original article Hit count: 113

Filed under:

I have defined a validate method for a Backbone.js Model. The problem is that even if validation fails (i.e. the Model.validate method returns a value) the post/put request is still sent to the server. This contradicts what is explained in the Backbone.js documentation. I cannot understand what I am doing wrong.

The following is the Model definition:

/**
 * Model - Contact
 */
var Contact = Backbone.Model.extend({
  urlRoot: '/contacts.json',
  idAttribute: '_id',
  defaults: function() {
    return {
      surname: '',
      given_name: '',
      org: '',
      phone: new Array(),
      email: new Array(),
      address: new Array({
        street: '',
        district: '',
        city: '',
        country: '',
        postcode: ''
      })
    };
  }
  validate: function(attributes) {
    if (typeof attributes.validationDisabled === 'undefined') {
      var errors = new Array();
      // Validate surname.
      if (_.isEmpty(attributes.surname) === true) {
        errors.push({
          type: 'form',
          attribute: 'surname',
          message: 'Please enter a surname.'
        });
      }
      // Validate emails.
      if (_.isEmpty(attributes.email) === false) {
        var emailRegex = /^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,6}$/i;
        // Stores indexes of email values which fail validation.
        var emailIndex = new Array();
        _.each(attributes.email, function(email, index) {
          if (emailRegex.test(email.value) === false) {
            emailIndex.push(index);
          }
        });
        // Create error message.
        if (emailIndex.length > 0) {
          errors.push({
            type: 'form',
            attribute: 'email',
            index: emailIndex,
            message: 'Please enter valid email address.'
          });
        }
      }

      if (errors.length > 0) {
        console.log('Form validation failed.');
        return errors;
      }
    }
  }
});

Here is the View which calls the Model.save() method (see: method saveContact() below). Note that other methods belonging to this View have not been included below for reasons of brevity.

/** 
 * View - Edit contact form 
 */
var EditContactFormView = Backbone.View.extend({
  initialize: function() {
    _.bindAll(this, 'createDialog', 'formError', 'render', 'saveContact', 'updateContact');
    // Add templates.
    this._editFormTemplate = _.template($('#edit-contact-form-tpl').html());
    this._emailFieldTemplate = _.template($('#email-field-tpl').html());
    this._phoneFieldTemplate = _.template($('#phone-field-tpl').html());
    // Get URI of current page.
    this.currentPageUri = this.options.currentPageUri;
    // Create array to hold references to all subviews. 
    this.subViews = new Array();
    // Set options for new or existing contact.
    this.model = this.options.model;
    // Bind with Model validation error event.
    this.model.on('error', this.formError);
    this.render();
  }
  /**
   * Deals with form validation errors
   */
  formError: function(model, error) {
    console.log(error);
  },
  saveContact: function(event) {
    var self = this;
    // Prevent submit event trigger from firing.
    event.preventDefault();
    // Trigger form submit event.
    eventAggregator.trigger('submit:contactEditForm');
    // Update model with form values.
    this.updateContact();
    // Enable validation for Model.  Done by unsetting validationDisabled
    // attribute. This setting was formerly applied to prevent validation 
    // on Model.fetch() events. See this.model.validate(). 
    this.model.unset('validationDisabled');
    // Save contact to database.
    this.model.save(this.model.attributes, {
      success: function(model, response) {
        if (typeof response.flash !== 'undefined') {
          Messenger.trigger('new:messages', response.flash);
        }
      },
      error: function(model, response) {
        console.log(response);
        throw error = new Error('Error occured while trying to save contact.');
      }
    }, { wait: true });
  },
  /**
   * Extract form values and update Contact.
   */
  updateContact: function() {
    this.model.set('surname', this.$('#surname-field').val());
    this.model.set('given_name', this.$('#given-name-field').val());
    this.model.set('org', this.$('#org-field').val());
    // Extract address form values.
    var address = new Array({
      street: this.$('input[name="street"]').val(),
      district: this.$('input[name="district"]').val(),
      city: this.$('input[name="city"]').val(),
      country: this.$('input[name="country"]').val(),
      postcode: this.$('input[name="postcode"]').val()
    });
    this.model.set('address', address);
  }
});

© Stack Overflow or respective owner

Related posts about backbone.js