particle-iot/ember-validations

Name: ember-validations

Owner: Particle

Description: Validations for Ember Objects

Forked from: DockYard/ember-validations

Created: 2016-03-03 18:48:24.0

Updated: 2016-03-03 18:48:25.0

Pushed: 2018-01-03 18:26:11.0

Homepage:

Size: 926

Language: JavaScript

GitHub Committers

UserMost Recent Commit# Commits

Other Committers

UserEmailMost Recent Commit# Commits

README

Ember Validations

Build Status

Building yourself
install
r install
r build

The builds will be in the dist/ directory.

Installing
With Ember-CLI

If you are using ember-cli you can add ember-validations to your package.json:

Dependencies": {
.
mber-validations": "~ 2.0.0"

You may want to be more precise with your version locking.

Without Ember-CLI

We will continue to build EmberValidations to the DockYard build server until ember-cli is officially recommended by Ember. You can select a build version from: http://builds.dockyard.com for use in Bower.

Looking for help?

If it is a bug please open an issue on GitHub.

Usage

You need to mixin EmberValidations into any Ember.Object you want to add validations to:

rt Ember from 'ember';
rt EmberValidations from 'ember-validations';

rt default Ember.Controller.extend(EmberValidations);

You define your validations as a JSON object. They should be added to the controller that represents the model in question. The keys in the object should map to properties. If you pass a JSON object as the value this will be seen as validation rules to apply to the property. If you pass true then the property itself will be seen as a validatable object.

rt Ember from 'ember';
rt EmberValidations from 'ember-validations';

rt default Ember.Controller.extend(EmberValidations, {
lidations: {
'model.firstName': {
  presence: true,
  length: { minimum: 5 }
},
'model.age': {
  numericality: true
},
'model.profile': true


Though not yet explicitly part of the API, you can also add validators to nested objects:

rt Ember from 'ember';
rt EmberValidations from 'ember-validations';

rt default Ember.Component.extend(EmberValidations, {
lidations: {
'user.firstName': {
  presence: true,
  length: { minimum: 5 }
}


This is useful for things like Components which don't act as proxies, but again, until this is officially built into the project, YMMV.

Note: If you override the init function, you must call _super()

rt Ember from 'ember';
rt EmberValidations from 'ember-validations';

rt default Ember.Controller.extend(EmberValidations, {
it: function() {
// this call is necessary, don't forget it!
this._super.apply(this, arguments);

// Your init code...


Validators
Absence

Validates the property has a value that is null, undefined, or ''

Options
xamples
nce: true
nce: { message: 'must be blank' }
Acceptance

By default the values '1', 1, and true are the acceptable values

Options
xamples
ptance: true
ptance: { message: 'you must accept', accept: 'yes' }
Confirmation

Expects a propertyConfirmation to have the same value as property. The validation must be applied to the property, not the propertyConfirmation (otherwise it would expect a propertyConfirmationConfirmation).

Options
xamples
irmation: true
irmation: { message: 'you must confirm' }
Exclusion

A list of values that are not allowed

Options
xamples
usion: { in: ['Yellow', 'Black', 'Red'] }
usion: { range: [5, 10], allowBlank: true, message: 'cannot be between 5 and 10' }
Format

A regular expression to test with the value

Options
xamples
at: { with: /^([a-zA-Z]|\d)+$/, allowBlank: true, message: 'must be letters and numbers only'  }
Inclusion

A list of the only values allowed

Options
xamples
usion: { in: ['Yellow', 'Black', 'Red'] }
usion: { range: [5, 10], allowBlank: true, message: 'must be between 5 and 10' }
Length

Define the lengths that are allowed

Options Messages
xamples
th: 5
th: [3, 5]
th: { is: 10, allowBlank: true }
th: { minimum: 3, maximum: 5, messages: { tooShort: 'should be more than 3 characters', tooLong: 'should be less than 5 characters' } }
th: { is: 5, tokenizer: function(value) { return value.split(''); } }
Numericality

Will ensure the value is a number

Options Messages
xamples
ricality: true
ricality: { messages: { numericality: 'must be a number' } }
ricality: { odd: true, messages: { odd: 'must be an odd number' } }
ricality: { onlyInteger: true, greaterThan: 5, lessThanOrEqualTo : 10 }
Presence

Validates the property has a value that is not null, undefined, or ''

Options
xamples
ence: true
ence: { message: 'must not be blank' }
Uniqueness

Not yet implemented.

Conditional Validators

Each validator can take an if or an unless in its options hash. The value of the conditional can be an inline function, a string that represents a property on the object, or a string that represents a function on the object. The result should be a boolean.

note that if is considered a keyword in IE8 and so you should put it in quotes

unction form
el.firstName': {
esence: {
'if': function(object, validator) {
  return true;
}



tring form
f 'canValidate' is a function on the object it will be called
f 'canValidate' is a property object.get('canValidate') will be called
el.firstName': {
esence: {
unless: 'canValidate'


Custom Validators
With Ember-CLI

You can place your custom validators into my-app/app/validators/{local,remote}/<name>:

rt Base from 'ember-validations/validators/base';

rt default Base.extend({
 ...

It is recommended that you separate between local and remote validators. However, if you wish you can place your validator into my-app/app/validators/<name>. However, any similarly named validator in local/ or remote/ has a higher lookup presedence over those in validators/.

The “native” validators that come with ember-validations have the lowest lookup priority.

Without Ember-CLI

You can add your validators to the global object:

rValidations.validators.local.<ClassName> =
rValidations.validators.Base.extend({
 ...

Creating

To create a new validator you need to override the call function. When the validator is run its call function is what handles determining if the validator is valid or not. Call has access to this.model, this.property. If the validation fails you must push the failing message onto the validator's this.errors array. A simple example of a validator could be:

rt Base from 'ember-validations/validators/base';
rt Ember from 'ember';

rt default Base.extend({
ll: function() {
if (Ember.isBlank(this.model.get(this.property))) {
  this.errors.pushObject("cannot be blank");
}


You may want to create a more complex validator that can observer for changes on multiple properties. You should override the init function to accomplish this:

rt Base from 'ember-validations/validators/base';
rt Ember from 'ember';

rt default Base.extend({
it: function() {
// this call is necessary, don't forget it!
this._super();

this.dependentValidationKeys.pushObject(this.options.alsoWatch);

ll: function() {
if (Ember.isBlank(this.model.get(this.property))) {
  this.errors.pushObject("cannot be blank");
}


The init function is given access to the this.options wich is simply a POJO of the options passed to the validator. dependentValidationKeys is the collection of paths relative to this.model that will be observed for changes. If any changes occur on any given path the validator will automatically trigger.

Inline Validators

If you want to create validators inline you can use the validator function that is part of the ember-validations export:

rt EmberValidations, { validator } from 'ember-validations';

.create({
lidations: {
'model.name': {
  inline: validator(function() {
    if (this.model.get('canNotDoSomething')) {
      return "you can't do this!"
    }
  })
}


Inside the validator function you have access to this.model which is a reference to the model. You must return an error message that will be attached to the errors array for the property it is created on. Return nothing for the validator to pass.

Alternatively if the property doesn't have any additional validations you can use a more concise syntax:

.create({
lidations: {
'model.name': EmberValidations.validator(function() {
  if (this.model.get('canNotDoSomething')) {
    return "you can't do this!"
  }
})


Running Validations

Validations will automatically run when the object is created and when each property changes. isValid states bubble up and help define the direct parent's validation state. isInvalid is also available for convenience.

If you want to force all validations to run simply call .validate() on the object. isValid will be set to true or false. All validations are run as deferred objects, so the validations will not be completed when validate is done. So validate returns a promise, call then with a function containing the code you want to run after the validations have successfully completed.

.validate().then(function() {
 all validations pass
er.get('isValid'); // true
atch(function() {
 any validations fail
er.get('isValid'); // false
inally(function() {
 all validations complete
 regardless of isValid state
r.get('isValid'); // true || false

Inspecting Errors

After mixing in EmberValidations into your object it will now have a .errors object. All validation error messages will be placed in there for the corresponding property. Errors messages will always be an array.

rt Ember from 'ember';
rt EmberValidations from 'ember-validations';

rt default Ember.Object.extend(EmberValidations, {
lidations: {
'model.firstName': { presence: true }


avascript
rt User from 'my-app/models/user';

 = User.create();
.validate().then(null, function() {
er.get('isValid'); // false
er.get('errors.firstName'); // ["can't be blank"]
er.set('firstName', 'Brian');
er.validate().then(function() {
user.get('isValid'); // true
user.get('errors.firstName'); // []


Testing
With Ember QUnit

For Ember Validations to work with Ember QUnit, you must define all your validations in the needs property of the moduleFor call. This will ensure Ember QUnit's isolated container will be able to locate the validations during testing.

rt { test, moduleFor } from 'ember-qunit';

leFor('controller:user/edit', 'UserEditController', {
eds: ['service:validations',
      'ember-validations@validator:local/presence',
      'ember-validations@validator:local/length',
      'validator:local/name',
      'validator:local/email'
      ]


('Controller Test', function() { ... });

Where UserEditController uses the built-in presence and length validators, and the locally defined name and email validators.

Test Helpers

To test whether your Ember validations are working correctly, you can use the test helpers:

testValidPropertyValues(propertyName, values [, context ])

testInvalidPropertyValues(propertyName, values [, context ])

rt { test, moduleFor } from 'ember-qunit';
rt {
stValidPropertyValues,
stInvalidPropertyValues
om '../../helpers/validate-properties';

leFor('controller:user', 'UserController', {
eds: ['ember-validations@validator:local/presence',
      'ember-validations@validator:local/length'
     ]


ValidPropertyValues('firstName', ['Winston', '12345']);
InvalidPropertyValues('firstName', ['abc', '', null, undefined]);

If a property's validation relies on another property, you can pass a context to the test helper:

ValidPropertyValues('lastName', ['Dog', '12345'], function(subject) {
bject.set('firstName', 'Boomer');


ValidPropertyValues('lastName', ['', null, undefined], function(subject) {
bject.set('firstName', null);

i18n

When you use ember-i18n your Ember.I18n.translations object should contain the following keys under the errors key:

r.I18n.translations = {
rors: {
inclusion: "is not included in the list",
exclusion: "is reserved",
invalid: "is invalid",
confirmation: "doesn't match {{attribute}}",
accepted: "must be accepted",
empty: "can't be empty",
blank: "can't be blank",
present: "must be blank",
tooLong: "is too long (maximum is {{count}} characters)",
tooShort: "is too short (minimum is {{count}} characters)",
wrongLength: "is the wrong length (should be {{count}} characters)",
notANumber: "is not a number",
notAnInteger: "must be an integer",
greaterThan: "must be greater than {{count}}",
greaterThanOrEqualTo: "must be greater than or equal to {{count}}",
equalTo: "must be equal to {{count}}",
lessThan: "must be less than {{count}}",
lessThanOrEqualTo: "must be less than or equal to {{count}}",
otherThan: "must be other than {{count}}",
odd: "must be odd",
even: "must be even"


Other Resources
Authors

We are very thankful for the many contributors

Versioning

This library follows Semantic Versioning

Want to help?

Please do! We are always looking to improve this library. Please see our Contribution Guidelines on how to properly submit issues and pull requests.

Legal

DockYard, LLC © 2013

@dockyard

Licensed under the MIT license


This work is supported by the National Institutes of Health's National Center for Advancing Translational Sciences, Grant Number U24TR002306. This work is solely the responsibility of the creators and does not necessarily represent the official views of the National Institutes of Health.