Default Options

Default options can be specified over a set of validations for a given attribute. Local properties will always take precedence.

Instead of doing the following:

const Validations = buildValidations({
  username: [
    validator('presence', {
      presence: true,
      description: 'Username'
    }),
    validator('length', {
      min: 1,
      description: 'Username'
    }),
    validator('my-custom-validator', {
      description: 'A username'
    })
  ]
});

We can declare default options:

const Validations = buildValidations({
  username: {
    description: 'Username'
    validators: [
      validator('presence', true),
      validator('length', {
        min: 1
      }),
      validator('my-custom-validator', {
        description: 'A username'
      })
    ]
  },
});

In the above example, all the validators for username will have a description of Username except that of the my-custom-validator validator which will be A username.

Global Options

If you have specific options you want to propagate through all your validation rules, you can do so by passing in a global options object. This is ideal for when you have a dependent key that each validator requires such as the current locale from your i18n implementation, or you want easily toggle your validations on/off. As of 3.x, all dependent keys must be prefixed with model.

const Validations = buildValidations(validationRules, globalOptions);
import Ember from 'ember';
import { validator, buildValidations } from 'ember-cp-validations';

const Validations = buildValidations({
  firstName: {
    description: 'First Name'
    validators: [
      validator('presence', {
        presence: true,
        dependentKeys: ['model.foo', 'model.bar']
      })
     ]
   },
  lastName: validator('presence', true)
}, {
  description: 'This field'
  dependentKeys: ['model.i18n.locale'],
  disabled: computed.readOnly('model.disableValidations')
});

Just like in the default options, locale validator options will always take precedence over default options and default options will always take precedence over global options. This allows you to declare global rules while having the ability to override them in lower levels.

This rule does not apply to dependentKeys, instead they all are merged. In the example above, firstName's dependentKeys will be ['model.i18n.locale', 'model.foo', 'model.bar']

Computed Options

All options can also be Computed Properties. These CPs have access to the model and attribute that is associated with the validator.

Please note that the message option of a validator can also be a function with the following signature.

const Validations = buildValidations({
  username: validator('length', {
    disabled: Ember.computed.not('model.meta.username.isEnabled'),
    min: Ember.computed.readOnly('model.meta.username.minLength'),
    max: Ember.computed.readOnly('model.meta.username.maxLength'),
    description: Ember.computed(function() {
      // CPs have access to the model and attribute
      return this.get('model').generateDescription(this.get('attribute'));
    }).volatile() // Disable caching and force recompute on every get call
  })
});

Nested Keys

When declaring object validations (not including Ember Data models), it is possible to validate child objects from the parent object.

import Ember from 'ember';
import { validator, buildValidations } from 'ember-cp-validations';

const Validations = buildValidations({
  'acceptTerms': validator('inclusion', { in: [ true ] }),
  'user.firstName': validator('presence', true),
  'user.lastName': validator('presence', true),
  'user.account.number': validator('number')
});

export default Ember.Component.extend(Validations, {
  acceptTerms: false,
  user:  {
    firstName: 'John',
    lastName: 'Doe' ,
    account: {
      number: 123456,
    }
  },
  isFormValid: Ember.computed.alias('validations.isValid'),
});