https://github.com/esbanarango/ember-model-validator
ember-cli addon adds validation support to your Ember-Data models.
https://github.com/esbanarango/ember-model-validator
ember ember-addon ember-cli ember-data emberjs javascript validator
Last synced: 28 days ago
JSON representation
ember-cli addon adds validation support to your Ember-Data models.
- Host: GitHub
- URL: https://github.com/esbanarango/ember-model-validator
- Owner: esbanarango
- License: mit
- Created: 2015-05-13T00:14:59.000Z (almost 10 years ago)
- Default Branch: master
- Last Pushed: 2024-11-21T15:59:58.000Z (6 months ago)
- Last Synced: 2025-04-01T00:34:56.719Z (about 1 month ago)
- Topics: ember, ember-addon, ember-cli, ember-data, emberjs, javascript, validator
- Language: JavaScript
- Homepage: http://esbanarango.github.io/ember-model-validator/
- Size: 8.32 MB
- Stars: 168
- Watchers: 7
- Forks: 35
- Open Issues: 14
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE.md
Awesome Lists containing this project
- awesome-ember - ember-model-validator - Add validations to your Ember Data models on an explicit and easy way, without a bunch a validations files around or complicated structure. (Packages / Data validation)
README
# Ember model validator
 [](https://github.com/esbanarango/ember-model-validator/actions/workflows/ci.yml) [](http://emberobserver.com/addons/ember-model-validator)
### [Live demo & Documentation](http://esbanarango.github.io/ember-model-validator/)
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.
## Purpose
This Ember addon was born from the necessity of having a validation support for models similar to [_Active Record Validations_](http://guides.rubyonrails.org/active_record_validations.html) on the Ruby on Rails land.
## Installation
Install **Ember-model-validator** is easy as:
`npm install ember-model-validator --save-dev`
or
`yarn add ember-model-validator --dev`## Usage
**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.
```js
// Using `except`
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'] });
```### Usage Example
```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') });
}
}
}
```### Or Usage in non Model(Controller, Componente, Object ...) Example
```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
```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-source`and `ember-data` v3.28 or above
---
- [Ember model validator](#ember-model-validator)
- [Live demo \& Documentation](#live-demo--documentation)
- [Purpose](#purpose)
- [Installation](#installation)
- [Usage](#usage)
- [Usage Example](#usage-example)
- [Or Usage in non Model(Controller, Componente, Object ...) Example](#or-usage-in-non-modelcontroller-componente-object--example)
- [TypeScript](#typescript)
- [Compatibility](#compatibility)
- [Validators](#validators)
- [Common options](#common-options)
- [Presence](#presence)
- [Acceptance](#acceptance)
- [Absence](#absence)
- [Format](#format)
- [Length](#length)
- [Options](#options)
- [Email](#email)
- [ZipCode](#zipcode)
- [Options](#options-1)
- [Hex Color](#hex-color)
- [Subdomain](#subdomain)
- [URL](#url)
- [Inclusion](#inclusion)
- [Exclusion](#exclusion)
- [Match](#match)
- [Options](#options-2)
- [Numericality](#numericality)
- [Options](#options-3)
- [Date](#date)
- [Options](#options-4)
- [Custom](#custom)
- [Password](#password)
- [Relations](#relations)
- [Using function to generate custom message](#using-function-to-generate-custom-message)
- [Example](#example)
- [I18n](#i18n)
- [Running Tests](#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](#using-function-to-generate-custom-message) 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](https://emberjs.com/api/ember/3.0/functions/@ember%2Futils/isBlank), all other validations for the field are skipped.
- `if` _option_. Validates **only** when the function passed returns true. `function(key,value, _this){...}`.### Presence
A value is not present if it is empty or a whitespace string. It uses [Ember.isBlank](https://emberjs.com/api/ember/3.0/functions/@ember%2Futils/isBlank) method. This can be also used on **async** `belongsTo` relations.
```js
validations = {
name: {
presence: true;
}
}
```### Acceptance
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.
### Absence
Validates that the specified attributes are absent. It uses [Ember.isPresent](https://emberjs.com/api/ember/3.0/functions/@ember%2Futils/isPresent) method.
```js
validations = {
login: {
absence: true;
}
}
```### Format
Specify a Regex to validate with. It uses the [match()](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/match) method from String.
```js
validations = {
legacyCode:{
format: { with: /^[a-zA-Z]+$/ }
}
}
```### Length
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'
}
}
}
}
```Validates the proper format of the email.
```js
validations = {
email: {
email: true
}
}
```### ZipCode
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](addon/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';
}
}
}
```### Hex Color
The value must be a correct Hexadecimal color.
```js
validations = {
favoriteColor: {
color: true;
}
}
```### Subdomain
The value must a well formatted subdomain. Here you can also specify reserved words.
```js
validations = {
mySubdomain: {
subdomain: {
reserved: ['admin', 'blog'];
}
}
}
```### URL
The value must a well formatted URL.
```js
validations = {
myBlog: {
URL: true;
}
}
```### Inclusion
The value has to be included in a given set.
```js
validations = {
name:{
inclusion: { in: ['Jose Rene', 'Aristi Gol', 'Armani'] }
}
}
```### Exclusion
The value can't be included in a given set.
```js
validations = {
name:{
exclusion: { in: ['Gionvany Hernandez', 'Wilder Medina'] }
}
}
```### Match
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!'
}
}
}
```### Numericality
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;
}
}
```### Date
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'
}
}
}
```### Custom
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."
}
];
}
}
```### Password
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](#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](#length)).```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
}
}
```### Relations
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.
> Note: The relations **have** to be [`embedded`](http://emberjs.com/api/data/classes/DS.EmbeddedRecordsMixin.html) or the promise has to be already resolved.
```js
validations = {
myHasManyRelation:{
relations: ['hasMany']
},
myBelongsToRelation:{
relations: ['belongsTo']
}
}
```### Using function to generate custom message
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](CONTRIBUTING.md) guide for details.