- Performs validation on ember object.
- Provides facility to perform validation on submit or focus out.
- Provides facility to perform validation when user starts typing, based on computed property rather using observer.
- Returns validation result as promise.
- Provides facility to return result as regular object rather than promise.
- Supports nested property validation.
Please add ember-validator
to your package.json
:
"devDependencies": {
...
"ember-validator": "1.4.0"
}
By default date validator is enabled in the validator, so you may need moment library.
If you want to skip importing moment library then set useDateValidator
to false
in ember-cli-build.js
.
var app = new EmberApp(defaults, {
emberValidator: {
useDateValidator: false
}
});
git clone
this repositoryyarn install
bower install
ember server
- Visit your app at http://localhost:4200.
yarn run test
(Runsember try:testall
to test your addon against multiple Ember versions)ember test
ember test --server
ember build
For more information on using ember-cli, visit http://www.ember-cli.com/.
If you find a bug or need help please open an issue on our Github.
Import EmberValidator
mixin and use this in any Ember Object
(route, controller, service).
import EmberValidator from 'ember-validator';
export default Ember.Controller.extend(EmberValidations, {});
If you want to add this mixin in a regular Ember.Object
which dont have container support, then
use initilizer to reopen EmberValidator
and assing container instance to it.
/**
app/instance-initializers/ember-validator.js
*/
import Ember from 'ember';
import EmberValidator from 'ember-validator';
export default {
name: 'ember-validator-reopen',
initialize: function(container) {
EmberValidator.reopen({
container: container
});
}
}
Ember.Object.extend(EmberValidator, {});
For older version of Ember. But we suggest not to use this approach.
/**
app/initializers/ember-validator.js
*/
import Ember from 'ember';
import EmberValidator from 'ember-validator';
export default {
name: 'ember-validator-reopen',
initialize: function(container) {
EmberValidator.reopen({
container: container
});
}
}
Ember.Object.extend(EmberValidator, {});
EmberValidator
exposes two functions to perform validation.
validateMap
createObjectWithValidator
computedValidateMap
validate
This functions is used to validate any object.
import Ember from 'ember';
import EmberValidator from 'ember-validator';
export default Ember.Controller.extend(EmberValidations, {
actions: {
var obj = Ember.Object.create({
userName: null,
password: null
});
var rules = {
userName: {
required: {
message: "Please enter user name"
}
},
password: {
required: {
message: "Please enter password"
}
}
};
var promise = this.validateMap({
model: obj, // Pass the object you want to validate
validations: rules // Define validation rules in the form of JSON,
});
promise.then(function() {
// When no errors or object is valid.
}).catch(function(result) {
// When there are errors or object is in valid.
// result.get('errors') -> Returns all error messages
// result.get('errors') -> Returns first message
// result.get('isValid') -> Returns true if the object is valid
// result.get('isInvalid') -> Returns true if the object is invalid
// result.get('hasError') -> Returns true if the object has errors
// result.get('userName.errors') -> Returns all error messages related with userName property
// result.get('userName.errors') -> Returns first message related with userName property
// result.get('userName.isValid') -> Returns true if userName property is valid
// result.get('userName.isInvalid') -> Returns true if userName property is invalid
// result.get('userName.hasError') -> Returns true if userName property has errors
}).finally(function() {
// Regardless object is valid or invalid.
});
}
});
Create or reopen object with validations. So validation will fired whenever the property value changes. In short triggers validator by computing property change.
Takes 3 arguments.
- model - Object to be validated.
- validations - Validations rules for an object.
- validateOnDirty - Default
false
. By default validation will happen irrespective of field is dirty or not. Set totrue
if you want to perform validation only if the field becomes dirty.
For example, if you are defining validation rules for a property called userName
for the object called model
, then validation result of that property is available in property userNameValidatorResult
model.get('userNameValidatorResult.errors') -> Returns all error messages related with userName property model.get('userNameValidatorResult.errors') -> Returns first message related with userName property model.get('userNameValidatorResult.isValid') -> Returns true if userName property is valid model.get('userNameValidatorResult.isInvalid') -> Returns true if userName property is invalid model.get('userNameValidatorResult.hasError') -> Returns true if userName property has errors
model.get('validatorResultHasError') -> Computed property which returns true if the validation result has any error model.get('validatorResultIsInValid') -> Computed property which returns true if model is not valid model.get('validatorResultIsValid') -> Computed property which returns true if model is valid model.get('validatorResultErrors') -> Computed property which array of all validation errors model.get('validatorResultObjectDirty') -> Computed property which returns true if the object is dirty model.get('validatorResultObjectClean') -> Computed property which returns true if the object is clean
// app/models/login.js
import Ember from 'ember';
export default Ember.Object.extend({
userName: null,
password: null
});
// app/routes/login.js
import Ember from 'ember';
import EmberValidator from 'ember-validator';
import LoginModel from 'app/models/login';
export default Ember.Route.extend(EmberValidations, {
model: function() {
var model = LoginModel.create();
var validations = {
userName: {
required: { message: 'Enter username' },
length: {
minimum: 4,
messages: {
minimum: 'Username is minimum of 4 characters'
}
}
},
password: {
required: { message: 'Enter Password' }
}
};
return this.createObjectWithValidator(model, validations, true);
}
});
// app/templates/login.hbs
<form {{action "login" on="submit"}}>
<p style="color:red">{{model.userNameValidatorResult.error}}</p>
{{input type="text" value=model.userName}}
<p style="color:red">{{model.passwordValidatorResult.error}}</p>
{{input type="password" value=model.password}}
<button type="submit">Login</button>
</form>
Same as createObjectWithValidator
, but we suggest to use createObjectWithValidator
.
// app/models/login.js
import Ember from 'ember';
export default Ember.Object.extend({
userName: null,
password: null
});
// app/routes/login.js
import Ember from 'ember';
import EmberValidator from 'ember-validator';
import LoginModel from 'app/models/login';
export default Ember.Route.extend(EmberValidations, {
model: function() {
var model = LoginModel.create();
var validations = {
userName: {
required: { message: 'Enter username' },
length: {
minimum: 4,
messages: {
minimum: 'Username is minimum of 4 characters'
}
}
},
password: {
required: { message: 'Enter Password' }
}
};
this.computedValidateMap({
model: model,
validations: validations,
validateOnDirty: true
});
}
});
// app/templates/login.hbs
<form {{action "login" on="submit"}}>
<p style="color:red">{{model.userNameValidatorResult.error}}</p>
{{input type="text" value=model.userName}}
<p style="color:red">{{model.passwordValidatorResult.error}}</p>
{{input type="password" value=model.password}}
<button type="submit">Login</button>
</form>
Use this function if you want to directly validate Ember Object
import Ember from 'ember';
import EmberValidator from 'ember-validator';
export default Ember.Controller.extend({
actions: {
var obj = Ember.Object.create(EmberValidations, { // Don't forget to reopen mixin to add container.
userName: null,
password: null
});
var rules = {
userName: {
required: {
message: "Please enter user name"
}
},
password: {
required: {
message: "Please enter password"
}
}
};
var promise = obj.validate({
validations: rules // Define validation rules in the form of JSON,
});
promise.then(function() {
// When no errors or object is valid.
}).catch(function(result) {
// When there are errors or object is in valid.
}).finally(function() {
// Regardless object is valid or invalid.
});
}
});
Both validateMap
and validate
is returning back promise.
If you dont want a promise, but only wants the result, then please pass flag noPromise
as true
var result = obj.validate({
validations: rules,
noPromise: true
});
var result = this.validateMap({
model: obj,
validations: rules,
noPromise: true
});
if (result.get('isValid')) {
// When object is valid
} else {
// When object is invalid
}
// result.get('errors') -> Returns all error messages
// result.get('errors') -> Returns first message
// result.get('isValid') -> Returns true if the object is valid
// result.get('isInvalid') -> Returns true if the object is invalid
// result.get('hasError') -> Returns true if the object has errors
// result.get('userName.errors') -> Returns all error messages related with userName property
// result.get('userName.errors') -> Returns first message related with userName property
// result.get('userName.isValid') -> Returns true if userName property is valid
// result.get('userName.isInvalid') -> Returns true if userName property is invalid
// result.get('userName.hasError') -> Returns true if userName property has errors
Supports to validation of object with an object.
In case of validation of a nested property, if you want to set validation result of the nested property in different parameter then supply 'errorProperty' along with validation rules.
var validations = {
'orders.detail': {
errorProperty: 'orderDetails',
required: true
}
};
var result = this.validateMap({
model: obj,
validations: validations,
noPromise: true
});
result.get('orderDetails.hasError');
Validate the property has value.
message
- Error message returned when required validation fails.
required: { message: 'Please enter a value' }
required: 'Please enter a value'
required: true
Validate the property dont have value.
message
- Error message returned when notrequired validation fails.
notrequired: { message: 'Value must be empty' }
notrequired: 'Value must be empty'
notrequired: true
Validate the property is boolean and has value true or false.
required
- Validates property istrue
.notrequired
- Validates property isfalse
.message
- Error message returned when validation fails.
If you want to override message of individual rule.
required
- Validates property istrue
.notrequired
- Validates property isfalse
.boolean
- Validates property isboolean
.
boolean: {
required: true
message: 'must be true'
}
boolean: {
notrequired: true
messages: {
boolean: 'must be boolean'
notrequired: 'must be false'
}
}
boolean: 'must be true'
boolean: true
Validate whether the property equals to the specified value.
message
- Error message returned when equals validation fails.accept
- The value to be compared.
equals: {
message: 'Only myusername is accepted',
accept: 'myusername'
}
Validate property with array of values, and the array of values contains/notcontains the property.
exclude
: An array of values that are excludedexludeRange
: An array of lower and upper bound, and values within this range is excluded.include
- An array of values that are excludedincludeRange
- An array of lower and upper bound, and values within this range is excluded.message
- Error message returned when validation fails.
If you want to override message of individual rule.
exclude
: Error message returned when exclude validation fails.exludeRange
: Error message returned when exludeRange validation fails.include
- Error message returned when include validation fails.includeRange
- Error message returned when includeRange validation fails.
contains: {
exclude: ['A', 'B', 'C'],
messages: {
exclude: 'Please enter valid value'
}
}
contains: {
exclude: ['A', 'B', 'C'],
message: 'Please enter valid value'
}
contains: {
excludeRange: [1, 10],
messages: {
excludeRange: 'cannot be between 1 and 10'
}
}
contains: {
include: ['A', 'B', 'C'],
messages: {
include: 'Please enter valid value'
}
}
contains: {
include: ['A', 'B', 'C'],
message: 'Please enter valid value'
}
contains: {
includeRange: [1, 10],
messages: {
includeRange: 'cannot be between 1 and 10'
}
}
Validate poperty with passed regular expression
hasAlphabet
- Set to true, to check has atleast one alphabethasUpperCase
- Set to true, to check has atleast one upper case alphabethasLowerCase
- Set to true, to check has atleast one lower case alphabethasNumber
- Set to true, to check has atleast one numberhasSpecial
- Set to true, to check atleast one special character. Supply a string of characters that you want to check or supply your own regex pattern.hasNoSpecial
- Set to true, to check no special charactershasNoSpace
- Set to true, to check no spaceswith
- The regular expression to test withwithout
- The regular expression to inverse testarray
- Array of regular expression, when you want to validate more than one regexmessage
- Error message returned when validation fails.
If you want to override message of individual rule.
hasAlphabet
- Error message returned when hasAlphabet validation fails.hasUpperCase
- Error message returned when hasUpperCase validation fails.hasLowerCase
- Error message returned when hasLowerCase validation fails.hasNumber
- Error message returned when hasNumber validation fails.hasSpecial
- Error message returned when hasSpecial validation fails.hasNoSpecial
- Error message returned when hasNoSpecial validation fails.hasNoSpace
- Error message returned when hasNoSpace validation fails.with
- Error message returned when with validation fails.without
- Error message returned when without validation fails.
pattern: {
with: /^([a-zA-Z])+$/,
messages: {
with: 'Must be alphabets'
}
}
pattern: {
with: /^([a-zA-Z])+$/,
message: 'Must be alphabets'
}
pattern: {
without: /^([a-zA-Z])+$/,
messages: {
without: 'Must not be alphabets'
}
}
pattern: {
without: /^([a-zA-Z])+$/,
message: 'Must not be alphabets'
}
pattern: {
array: [
{
with: /^([a-zA-Z])+$/,
message: 'Must be alphabets'
},
{
without: /^([a-zA-Z])+$/, // Different expression
message: 'Must be alphabets' // Message to be displayed
}
]
}
Validate whether the property is email.
with
- The regular expression to test with, if you are not happy with the default email pattern.message
- Error message returned when email validation fails.
email: {
message: "Invalid email"
}
email: true
email: 'Invalid email'
email: {
with: /^(([^<>()\[\]\\.,;:\s@\"]+(\.[^<>()\[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
message: "Invalid email"
}
Validate whether the property is ssn. Default pattern of ssn NNN-NN-NNNN. change this by setting with
property
format1
: 999-99-9999. Set totrue
if you want to validate this pattern.format2
: 999999999. Set totrue
if you want to validate this pattern.format3
: 999.99.9999. Set totrue
if you want to validate this pattern.all
: Set to true, if you want to validate with all the default formats.message
- Error message returned when email validation fails.
ssn: {
format1: true,
message: "Invalid ssn"
}
ssn: {
all: true,
message: "Invalid ssn"
}
ssn: true
ssn: 'Invalid ssn'
Validate whether the property is valid zip. Default pattern of ssn NNNNN or NNNNN-NNNN. change this by setting with
property
with
- The regular expression to test with, if you are not happy with the default zip pattern.message
- Error message returned when zip validation fails.
zip: {
message: "Invalid zip"
}
zip: true
zip: 'Invalid zip'
Validate whether the property is valid phone. Default supported phone number pattern are.
format1
: (999) 999 9999. Set totrue
if you want to validate this pattern.format2
: (999) 999-9999. Set totrue
if you want to validate this pattern.format3
: (999)999 9999. Set totrue
if you want to validate this pattern.format4
: (999)999-9999. Set totrue
if you want to validate this pattern.format5
: (999)9999999. Set totrue
if you want to validate this pattern.format6
: 999 999 9999. Set totrue
if you want to validate this pattern.format7
: 999-999-9999. Set totrue
if you want to validate this pattern.format8
: 999.999.9999. Set totrue
if you want to validate this pattern.format9
: 9999999999. Set totrue
if you want to validate this pattern.all
: Set to true, if you want to validate with all the default formats.message
: Error message returned when phone validation fails.
phone: {
format1: true,
format5: true,
message: "Invalid phone"
}
// This matches format1 and format4 patterns of phone number
phone: {
all: true
message: "Invalid phone"
}
phone: true
phone: 'Invalid phone'
Validate length of property
minimum
- The minimum length of the valuemaximum
- The maximum length of the valueis
- The exact length of the valuetokenizer
- A function that tokenize the string to get length, by default tokenized with ''.message
- Error message returned when validation fails.
If you want to override message of individual rule.
minimum
- Error message returned when minimum validation fails.maximum
- Error message returned when maximum validation fails.is
- Error message returned when is validation fails.
length: {
minimum: 4,
maximum: 20,
messages: {
minimum: 'Must be more than 4 characters',
maximum: 'Must be less than 20 characters'
}
}
length: {
is: 4,
messages: {
is: 'Must be contains 4 characters'
}
}
length: {
is: 4,
message: 'Must be contains 4 characters'
}
length: {
is: 4,
message: 'Must be contains 4 characters'
tokenizer: function(value) {
return value.split(' ');
}
}
Validates property is a number, comma separated numbers also supported. Default pattern of numbers /^\d+(,\d{3})(.\d)?$/
You can change this by setting pattern
property of the options.
By default maximum allowed decimal length is 12 and maximum allowed fraction length is 2.
pattern
- Default pattern for number /^\d+(,\d{3})(.\d)?$/, set this if you want any other pattern.integer
- Validates property is a integergreaterThan
- Validates property is greater thangreaterThanOrEqualTo
- Validates property is greater than or equal toequalTo
- Validates property is equal tonotEqualTo
- Validates property is not equal tolessThan
- Validates property is less thanlessThanOrEqualTo
- Validates property is less than or equal toodd
- Validates property is oddeven
- Validates property is evendecimal
- Validates maximum no of decimal digits. Default allowed digits is 12.fraction
- Validates maximum no of fraction digits. Default allowed digits is 2.range
- Validates number falls in the range. This must be an array holding upper and lower limitbetween
- Validates number falls between the given range. This must be an array holding upper and lower limit. Difference with range is this validation fails if value is equal to upper or lower limit.message
- Error message returned when validation fails.
If you want to override message of individual rule.
numeric
- Error message returned when numeric validation fails.integer
- Error message returned when integer validation fails.greaterThan
- Error message returned when greaterThan validation fails.greaterThanOrEqualTo
- Error message returned when greaterThanOrEqualTo validation fails.equalTo
- Error message returned when equalTo validation fails.notEqualTo
- Error message returned when notEqualTo validation fails.lessThan
- Error message returned when lessThan validation fails.lessThanOrEqualTo
- Error message returned when lessThanOrEqualTo validation fails.odd
- Error message returned when odd validation fails.even
- Error message returned when even validation fails.decimal
- Error message returned when decimal validation fails.fraction
- Error message returned when fraction validation fails.range
- Error message returned when range validation fails.between
- Error message returned when between validation fails.
numeric: {
integer: true,
messages: {
integer: 'must be an integer'
}
}
numeric: {
lessThan: 10,
messages: {
lessThan: 'must be less than 10'
}
}
numeric: {
greaterThan: "10,000.12",
decimal: 5,
fraction: 2,
messages: {
greaterThan: 'must be greater than 10,000.12'
decimal: 'must be max of 5 decimal digits',
fraction: 'must be max of 2 fraction digits'
}
}
numeric: {
greaterThan: "10,000.12",
decimal: 5,
fraction: 2,
message: 'Valid number'
messages: {
greaterThan: 'must be greater than 10,000.12'
}
}
Perform date validation. Property can be Date object, moment object or string. If the property is string then set format
option
format
- Format of the source date, only if property is date in string.time
- By default time is not allowed while performing validations, set this to true, if you want to validate time also.weekend
- Validates property is a weekend.onlyWeekend
- Validates property is a only saturday or sunday.before
- Validates property is before target datebeforeSame
- Validates property is before or same as target datesame
- Validates property is same as target datenotSame
- Validates property is not same as target dateafter
- Validates property is after target dateafterSame
- Validates property is after or same as target datemessage
- Error message returned when validation fails.
The below two are options for same, before, after, beforeSame and afterSame
target
- Date to be compared with. This can be date object, moment object or string. If the property is string then setformat
option.format
- Format of target date, if it is string.
If you want to override message of individual rule.
date
- Error message to be displayed if date is not valid.weekend
- Error message returned when weekend validation fails.onlyWeekend
- Error message returned when onlyWeekend validation fails.before
- Error message returned when before validation fails.beforeSame
- Error message returned when beforeSame validation fails.same
- Error message returned when same validation fails.notSame
- Error message returned when notSame validation fails.after
- Error message returned when after validation fails.afterSame
- Error message returned when afterSame validation fails.
date: {
weekend: true,
messages: {
weekend: 'must not be weekend'
}
}
// If property date is 'Nov/01/2015'
date: {
format: 'MMM/DD/YYYY',
before: {
target: 'Oct/31/2015',
format: 'MMM/DD/YYYY'
},
afterSame: {
target: new Date()
},
messages: {
before: 'date must be before Oct/31/2015',
afterSame: 'date must be after new Date()'
}
}
In some cases we may want to execute the function only if certain conditions are satisfied.
Please use if
and unless
options in validation rules.
if
- Validator will be executed only if the supplied call back returns true. This can be a function or a boolean.unless
- Validator will be executed only if the supplied call back returns false. This can be a function or a boolean.
userName: {
length: {
'if': function(model, property) {
return true;
}
}
}
password: {
numeric: {
unless: function(model, property) {
return false;
}
}
}
Conditional validators are also added in property level, so it wont validate any validators defined for the property.
userName: {
'if': function(model, property) {
return true;
},
length: {
}
}
password: {
unless: function(model, property) {
return false;
},
numeric: {
}
}
You can place your custom validators into my-app/app/validators/<name>
:
/**
my-app/app/validators/myvalidator.js
*/
import Validator from 'ember-validator/validators/validator';
export default Validator.extend({
perform: function() {
// Do your validation login here.
}
});
userName: {
myvalidator: {
...
}
}
If you want to create validators on the fly then,
import { inlineValidator } from 'ember-validator';
{
userName: {
custom: inlineValidator(function(model, property) {
return 'Error message';
})
}
}