ember addon. It adds validation support to your Ember-Data models.
npm install ember-model-validator!Download count all time  
Add validations to your _Ember Data_ models on an explicit and easy way, without a bunch a validations files around or complicated structure.
This README outlines the details of collaborating on this Ember addon.
This Ember addon was born from the necessity of having a validation support for models similar to _Active Record Validations_ on the Ruby on Rails land.
Install Ember-model-validator is easy as:
npm install ember-model-validator --save-dev
oryarn add ember-model-validator --dev
Ember-model-validator provides a decorator to be included in your models for adding validation support. This decorator can be imported from your app's namespace (e.g. import { modelValidator, objectValidator } from 'ember-model-validator'; in your models).
By including Ember-model-validator's decorator into your model, this will have a validate function available, it is a _synchronous_ function which returns either true or false.
You can also pass an _option_ hash for excluding or forcing certain attributes to be validated, and to prevent errors to be added.
``jsexcept
// Using
myModel.validate({ except: ['name', 'cellphone'] });
// Using only
myModel.validate({ only: ['favoriteColor', 'mainstreamCode'] });
// Using addErrors`
myModel.validate({ addErrors: false });
// ^ This will validate the model but won't add any errors.
To target specific validations when using except/only, pass the validations' names along the attribute's name:
`js`
// This runs all validations, except name's presence and length validations and
// any email validations.
// Other name validations are still run.
myModel.validate({ except: ['name:presence,length', 'email'] });
`js
import Model, { attr } from '@ember-data/model';
import { modelValidator } from 'ember-model-validator';
@modelValidator
export default class MyModel extends Model {
@attr('string') fullName;
@attr('string') fruit;
@attr('string') favoriteColor;
validations = {
fullName: {
presence: true
},
fruit: {
presence: true
},
favoriteColor: {
color: true
}
};
}
`
After setting the validations on your model you will be able to:
`js
import Controller from '@ember/controller';
import { action } from '@ember/object';
export default class MyController extends Controller {
@action
async saveFakeModel() {
const fakeModel = this.model;
if (fakeModel.validate()) {
await fakeModel.save();
} else {
console.log({ errors: fakeModel.get('errors') });
}
}
}
`
`js
import Component from '@ember/component';
import { objectValidator } from 'ember-model-validator';
@objectValidator
export default class MyComponent extends Component {
test = 'ABC',
validations = {
test: {
presence: true
}
}
};
`
typescript
import Model, { attr } from '@ember-data/model';import { modelValidator, type ValidationsConfig, type ValidatedModel } from 'ember-model-validator';
// https://github.com/microsoft/TypeScript/issues/4881
interface MyModel extends ValidatedModel, Model {}
@modelValidator
class MyModel extends Model {
@attr('string') declare name: string;
validations: ValidationsConfig = {
name: {
presence: true,
},
email: {
presence: true,
email: true,
},
};
}
export default MyModel;
declare module 'ember-data/types/registries/model' {
export default interface ModelRegistry {
'my-model': MyModel;
}
}
`
Compatibility
-
ember-sourceand ember-data v3.28 or above---
- Ember model validator
- Live demo \& Documentation
- Purpose
- Installation
- Usage
- Usage Example
- Or Usage in non Model(Controller, Componente, Object ...) Example
- TypeScript
- Compatibility
- Validators
- Common options
- Presence
- Acceptance
- Absence
- Format
- Length
- Options
- Email
- ZipCode
- Options
- Hex Color
- Subdomain
- URL
- Inclusion
- Exclusion
- Match
- Options
- Numericality
- Options
- Date
- Options
- Custom
- Password
- Relations
- Using function to generate custom message
- Example
- I18n
- Running Tests
Validators
##### Common options
All validators accept the following options
-
message _option_. Overwrites the default message, it can be a String (with a {value} in it for value interpolation) or a function that returns a string.
- errorAs _option_. Sets the _key_ name to be used when adding errors (default to property name).
- allowBlank _option_. If set to true and the value is blank as defined by Ember.isBlank, all other validations for the field are skipped.
- if _option_. Validates only when the function passed returns true. function(key,value, _this){...}.$3
A value is not present if it is empty or a whitespace string. It uses Ember.isBlank method. This can be also used on async
belongsTo relations.`js
validations = {
name: {
presence: true;
}
}
`$3
These values:
['1', 1, true] are the acceptable values. But you can specify yours with the accept option.`js
validations = {
acceptConditions: {
acceptance: {
accept: 'yes';
}
}
}
`> The
accept option receives either a string or an array of acceptable values.$3
Validates that the specified attributes are absent. It uses Ember.isPresent method.
`js
validations = {
login: {
absence: true;
}
}
`$3
Specify a Regex to validate with. It uses the match() method from String.
`js
validations = {
legacyCode:{
format: { with: /^[a-zA-Z]+$/ }
}
}
`$3
Specify the lengths that are allowed.
##### Options
- A
number. The exact length of the value allowed (Alias for is).
- An array. Will expand to minimum and maximum. First element is the lower bound, second element is the upper bound.
- is _option_. The exact length of the value allowed.
- minimum _option_. The minimum length of the value allowed.
- maximum _option_. The maximum length of the value allowed.`js
validations = {
socialSecurity: {
length: 5
},
nsaNumber: {
length: [3, 5]
},
chuncaluchoNumber: {
length: { is: 10, message: 'this is not the length of a chuncalucho' }
},
hugeName:{
length: {
minimum: 3,
maximum: 5
}
},
smallName:{
length: {
maximum: {
value: 3,
message: 'should be smaller'
}
}
}
}
`$3
Validates the proper format of the email.
`js
validations = {
email: {
email: true
}
}
`$3
The value must be a correct zipcode. The
countryCode is optional and defaults to 'US'.Countries supported and regular expressions used can be found in postal-codes-regex.js
##### Options
-
countryCode _option_. The code of the country for which the postal code will be validated.`js
validations = {
postalCode: {
// If no countryCode is specified, 'US' is used as default
zipCode: true;
}
}
``js
validations = {
postalCodeUK: {
zipCode: {
countryCode: 'UK';
}
}
}
`$3
The value must be a correct Hexadecimal color.
`js
validations = {
favoriteColor: {
color: true;
}
}
`$3
The value must a well formatted subdomain. Here you can also specify reserved words.
`js
validations = {
mySubdomain: {
subdomain: {
reserved: ['admin', 'blog'];
}
}
}
`$3
The value must a well formatted URL.
`js
validations = {
myBlog: {
URL: true;
}
}
`$3
The value has to be included in a given set.
`js
validations = {
name:{
inclusion: { in: ['Jose Rene', 'Aristi Gol', 'Armani'] }
}
}
`$3
The value can't be included in a given set.
`js
validations = {
name:{
exclusion: { in: ['Gionvany Hernandez', 'Wilder Medina'] }
}
}
`$3
Specify the attribute to match with.
##### Options
- A
string. The name of the attribute to match with (Alias for attr).
- attr _option_. The name of the attribute to match with.`js
validations = {
email:{
match: 'confirmationEmail'
},
password:{
match: {
attr: 'passwordConfirmation',
message: 'sup, it is not the same!'
}
}
}
`$3
The value has to have only numeric values.
##### Options
-
onlyInteger _option_. The value must be an integer.
- greaterThan _option_. The value must be greater than the supplied value.
- greaterThanOrEqualTo _option_. The value must be greater or equal to the supplied value.
- equalTo _option_. The value must be equal to the supplied value.
- lessThan _option_. The value must be less than the supplied value.
- lessThanOrEqualTo _option_. The value must be less or equal to the supplied value.
- odd _option_. The value must be odd.
- even _option_. The value must be even.`js
validations = {
lotteryNumber: {
numericality: true;
}
}
`$3
The value must be a
Date object or a string that produces a valid date when passed to the Date constructor.##### Options
-
before _option_. The value must be before the supplied date.
- after _option_. The value must be after the supplied date.`js
validations = {
birthDate: {
date: {
before: new Date()
}
},
signupDate: {
date: {
after: '2015-01-01'
}
}
}
`$3
Define a custom callback function to validate the model's value. The validation callback is passed 3 values: the _key_, _value_, _model's scope_. return true (or a truthy value) to pass the validation, return false (or falsy value) to fail the validation.
`js
validations = {
lotteryNumber: {
custom: function(key, value, model){
return model.get('accountBalance') > 1 ? true : false;
}
}
}
`this has the same action as above except will use a custom message instead of the default.
`js
validations = {
lotteryNumber: {
custom: {
validation: function(key, value, model){
return model.get('accountBalance') > 1 ? true : false;
},
message: 'You can\'t win off of good looks and charm.'
}
}
}
`to have multiple custom validation functions on the same property, give 'custom' an array of either of the two syntax above.
`js
validations = {
lotteryNumber: {
custom: [
{
validation: function(key, value, model) {
return model.get('accountBalance') > 1 ? true : false;
},
message: "You can't win off of good looks and charm."
},
{
validation: function(key, value, model) {
return model.get('accountBalance') > 1 ? true : false;
},
message: "You can't win off of good looks and charm."
}
];
}
}
`$3
A set of validators which are especially useful for validating passwords. Be aware that these all of these password-aimed validations will work standalone and carry the same common options with the rest of the validations. They don't only work for passwords!
-
mustContainCapital (capital case character).
- mustContainLower (lower case character).
- mustContainNumber
- mustContainSpecial
- length (explained in-depth above).`js
validations = {
password: {
presence: true,
mustContainCapital: true,
mustContainLower: true,
mustContainNumber: true,
mustContainSpecial: {
message: 'One of these characters is required: %@',
acceptableChars: '-+_!@#$%^&*.,?()'
},
length: {
minimum: 6
}
},
someOtherThing: {
mustContainSpecial: true
}
}
`$3
This validator will run the
validate() function for the specific relation. If it's a DS.hasMany relation then it will loop through all objects.embedded or the promise has to be already resolved.`js
validations = {
myHasManyRelation:{
relations: ['hasMany']
},
myBelongsToRelation:{
relations: ['belongsTo']
}
}
`$3
You can pass a function to generate a more specific error message. Some scenarios are:
- When the message varies depending of the attribute value.
- When you want to use model attributes in the message.
The message function receives the attribute name, the value of the attribute and the model itself.
NOTE: If the function doesn't return a string the default message is going to be used.
##### Example
`js
import Model, { attr } from '@ember-data/model';
import { modelValidator } from 'ember-model-validator';@modelValidator
export default class MyModel extends Model {
@attr('number', { defaultValue: 12345 }) otherCustomAttribute;
validations = {
otherCustomAttribute: {
custom: {
validation: function(key, value) {
return value.toString().length === 5 ? true : false;
},
message: function(key, value, _this) {
return key + ' must have exactly 5 digits';
}
}
}
};
}
`I18n
Set
validatorDefaultLocale in your config enviroment a language, for now it's possible use 'en', 'fr', 'es', 'uk', 'hu', 'sr', 'sr-cyrl' or 'pt-br', default is 'en';`js
//config/environment.js
...
ENV:{
...
APP:{
validatorDefaultLocale: 'pt-br'
}
...
}
...
`Running Tests
-
npm test (Runs ember try:each to test your addon against multiple Ember versions)
- ember test
- ember test --server`See the Contributing guide for details.