Validation

in NestedTypes and NestedReact

Vlad "Gaperton" Balin & Volicon Inc.

Attribute-level checks

let M = Model.extend({
    defaults : {

// ↓ Simple check ↓
        a : Number.has.check( x => x > 0 ),
        
// ↓ Check with an error object ↓
        b : Number.has
                  .check( x => x < 0, ‘b should be negative’ ),

// ↓ Sequence of checks with different error objects ↓
        c : Number.has
                  .check( x => x > 0, ‘c should be positive’ )

                  .check( x => x < 5, ‘c should be lesser than 5’ )
    }
});

Object-level checks

let M = Model.extend({
    defaults : {
        a : Number.has.check( x => x > 0 ),

        b : Number.has
                  .check( x => x < 0, ‘b should be negative’ ),

        c : Number.has
                  .check( x => x > 0, ‘c should be positive’ )

                  .check( x => x < 5, ‘c should be lesser than 5’ )
    },

// ↓ Additional object-level check returning error object ↓
    validate(){
        if( this.a > this.b ) return "That's bad";
    }
});

Model validation

  • Model is valid whenever all object and attribute level checks pass.
  • Default checks for attribute types:
    • Number is valid unless it’s NaN or Infinity
    • Date is valid unless it’s ‘Invalid date’
    • Model/Collection is valid whenever nested object is valid.
    • Model.from is always valid.
  • .has.check overrides default checks.
  • Invalid models are rejected by model.save()

Collection validation

  • Collection is valid whenever all models are valid, and object-level check pass
  • Collection.subsetOf is valid if its object-level check pass
  • Collection and Model share uniform Validation API

Validation API

// ↓ Both model and Collection ↓

object.isValid() == true or false

// Result of object's validation, containing all errors
object.validationError == null or ValidationError

// ↓ Model only ↓

// check if specific model's attribute is valid
model.isValid( 'attr' ) == true or false

// value links contains attribute's error object
model.getLink( 'attr' ) == { value, requestChange, validationError }

// ↓ Collection only ↓

// check is specific model in collection is valid
collection.isValid( modelId ) == true or false

ValidationError

{
    error : `as returned from object.validate()`,

// ↓ nested object's validation errors ↓
    nested : {


    // ↓ for the Model ↓
        attrName : `as returned from attr’s .has.check( x )`
                ||
 `nested object’s validationError
`

    // ↓ for the Collection
 ↓
        modelId : `model’s validationError`
    }
    
    length : `total errors count`
    
    _changeToken: `version's marker used to invalidate cache`
}

model.getLink( ‘attr’ )

{
// ↓ Attribute's value ↓
    value : model.attr,

// ↓ Callback to set new value ↓
    requestChange : x => model.attr = x,

// ↓ Attribute's error, if present ↓
    validationError : model.validationError.nested.attr
                   || null
}

How it works

  • Validation is performed on first access of object.validationError property
  • Validation result is cached across model/collection tree, so consequent reads of validationError are cheap.
  • Models will be validated again only if they was actually changed.

See us on github

Validation in NestedReact

By Vlad Balin

Validation in NestedReact

  • 1,482