Ced YahooB
Ced YahooB

Reputation: 151

How to validate model using collection.create()

I'm trying to make a form validated before submit. For this, I defined a create method within the View which is responsible to call collection.create() method to create the model.

Here is a sample code:

app.ContactCreateView = Backbone.View.extend({
    template: _.template($('#tpl-create-contact').html()),
    initialize: function () {
      this.router = new app.ContactsRouter();
      this.contacts = new app.ContactsCollection();
    },
    events: {
      'click #btn-create' : 'create',
      'click #btn-cancel' : 'cancel',
    },
    render: function() {
      this.$el.html(this.template());
      return this;
    },
    getAttributes: function () {
      console.log('getAttributes()');
      var attr = { 
        name: $('#input-name').val().trim(),
        category: $('#input-category').val().trim(),
        phone: $('#input-phone').val().trim(),
        email: $('#input-email').val().trim(),
      };
      console.log('attr : ' + JSON.stringify(attr))
      return attr;
    },
    create: function () {
      console.log('create()');
      // Create the Model
      this.contacts.create(this.getAttributes(), {
        wait : true,      
        success: function () {
          console.log('success');
          //this.hideErrors();
          var router = new app.ContactsRouter();
          router.navigate('contacts', true);
        },
        error: function () {
          console.log('error(s)')
          //this.showErrors(errors);
        }
      });

    },

The 'success' callback is well called but I don't manage to get the 'error' callback called once the model.validate() method is failing.

Here is the model with the validate method :

app.ContactModel = Backbone.Model.extend({
    urlRoot: '/user',
    // Default attributes for the Contact
    defaults: {
      name: null,
      phone: null,
      email: null,
      category: null,
      photo: "/images/placeholder.png"
    },
    validate: function(attrs) {
      console.log('validate() : ' + JSON.stringify(attrs));
      var errors = [];
      if (!attrs.name) {
        errors.push({name: 'name', message: 'Please fill name field.'});
      }
      if (!attrs.category) {
        errors.push({name: 'category', message: 'Please fill category field.'});
      }
      console.log('errors : ' + JSON.stringify(errors));
      return errors.length > 0 ? errors : false;
    }
  });

And the collection:

  app.ContactsCollection = Backbone.Collection.extend({
    model: app.ContactModel,
    url: '/user',
    //localStorage: new Backbone.LocalStorage('contacts-backbone'),

    getById: function (iId) {
        return this.where({id: iId});
    },
    getByName: function (iName) {
        return this.where({name: iName});
    }
  });

I really don't understand what I'm doing wrong... If somebody can help me :-( Regards,

Upvotes: 0

Views: 87

Answers (2)

StateLess
StateLess

Reputation: 5402

when the validation is failed error callback is not called , it trigger an "invalid" event on model, and set the validationError property on the model.

method 1(listening on model):

app.ContactModel = Backbone.Model.extend({
    urlRoot: '/user',
   //your error catched here
   initialize : function(){
        this.on("invalid",function(model,error){
            alert(error);
        });
    defaults: {
      name: null,
      phone: null,
      email: null,
      category: null,
      photo: "/images/placeholder.png"
    },
    validate: function(attrs) {
      console.log('validate() : ' + JSON.stringify(attrs));
      var errors = [];
      if (!attrs.name) {
        errors.push({name: 'name', message: 'Please fill name field.'});
      }
      if (!attrs.category) {
        errors.push({name: 'category', message: 'Please fill category field.'});
      }
      console.log('errors : ' + JSON.stringify(errors));
      return errors.length > 0 ? errors : false;
    }
  });

method 2 (check whether validationError property is set in your view):

     create: function () {
      console.log('create()');
      // Create the Model
      this.contactModel.save(this.getAttributes(), {
        wait : true,      
        success: function () {
          console.log('success');
          this.contacts.add(this.contactModel);
          var router = new app.ContactsRouter();
          router.navigate('contacts', true);
        },
        error: function () {
          console.log('error(s)')
        }
      });
      //your error catched here
      if (this.contactModel.validationError) {
      alert(this.contactModel.validationError)
    }
    },

Upvotes: 1

Tom Hammond
Tom Hammond

Reputation: 6080

So I played around with this for a while in an app I'm currently working on and found it kind of irritating and never really got it to work.

Instead I went the jQuery validation route and found it very helpful for doing validations. I highly recommend checking it out! It has a lot of built in validations you can just use and you can also override the error messages that display (also built in).

Example - I wanted a number only text field (excuse the coffeescript) :).

jQuery.validator.setDefaults(
            debug: true,
            success: "valid")
        if @model.get('number_only')
            $('#number_only').validate({
                debug: true,
                rules: {
                    "number[entry]": {
                        required: true,
                        range: [@model.get('min_number'), @model.get('max_number')],
                        number: true
                    }
                },
                messages: {
                    "number[entry]": {
                        required: "This field is required. Please enter a numeric value.",
                        min: jQuery.validator.format("Please enter a value greater than or equal to {0}."),
                        max: jQuery.validator.format("Please enter a value less than or equal to {0}."),
                        number: "Please enter a numeric value"
                        range: jQuery.validator.format("Please enter a value between {0} and {1}.")
                    }
                }
            })

If that doesn't really get what you want (seemed like you maybe are more interested in displaying the errors your server sends back whereas this route would more be validating the content before saving your model) let me know and I can see if I can figure out your problem.

Upvotes: 0

Related Questions