Angular Form Validations

Ibrahim Muhammad

Twitter: @ibrahimm

http://ibrahimmuhammad.com

https://slides.com/ibrahimm/ng-validation

<input type="number"
       ng-model="creditCard.number"
       name="number"
       min="0" max="9999999999999999"
       integer />
<span ng-show="form.size.$error.integer">
    The value is not a valid integer!
</span>
<span ng-show="form.size.$error.min || form.size.$error.max">
    The value must be in range 0 to 9999999999999999!
</span>
  • Validation goes in the views
  • Works well in a number of places

The Angular Way

The good and the bad

The Good:

  • Easy - angular directives to help
  • Customizable view to view

The Bad:

  • Can easily be not DRY
  • Custom validations are hard to generalize in directives

Error Object

{
    "expiryDate": ["Expiry date must be after today"],
    "number": false // or missing
}

Moving to a Service

function validate(){
    var errors = {};
    if (this.expiryDate > today) {
        addError(errors, 'name', 'Expiry date must be after today');
    }
    return errors;
}
  • DRYer, if used in multiple views
  • We lose the angular provided helpers

Validation helpers

function validateDateGreaterThan(model, attribute, value) {
    if (model[attribute]) <= value) {
        addError(model, attribute, attribute + ' must be after '+ value);
        // error added to model.errors
    }
}

validateDateGreaterThan(creditCard, 'expiryDate', Date.now())

More Delarative

var schema = {
    'expiryDate': {
        'min': new Date("1 Jan 1980"),
        'max': Date.now(),
        'type': 'date'
    }
}
var errors = validate(model, schema);
  • possibly use JSON schema with existing validators

Custom Validations (1)

var schema = {
    'number': {
        'min': function(creditcard) {
            var len = creditcard.number.length;
            if (creditcard.type === 'visa'){
                return (len === 13 || len == 16);
            } else { //mastercard
                return len === 16;
            }
        }
    }
}
  • Use functions or values (inspiration from grunt)

Custom Validations (2)

var schema = {
    'number': {
        'checksum': function(creditcard) {
            var errorMessage = "Checksum is not valid";
            return [isChecksumValid(creditcard.number), errorMessage];
        }
    }
}

More Human

validate(creditcard)
    .field('number').type('number')min(0).max(9999999999999999).checksum()
    .field('expiryDate').type('date').min(Date(MIN_DATE)).max(Date.Today())
  • Use method chaining

Thanks!

Interested in OS library that does this? @ibrahimm

Angular JS Form Validations

By Ibrahim Muhammad

Angular JS Form Validations

Pros and cons of Angular style form validations, how to move validation logic out of the views, and how to develop a more declarative style of validations in services.

  • 1,474