{"id":13806165,"url":"https://github.com/esbanarango/ember-model-validator","last_synced_at":"2025-04-08T01:35:34.856Z","repository":{"id":31949293,"uuid":"35519092","full_name":"esbanarango/ember-model-validator","owner":"esbanarango","description":"ember-cli addon adds validation support to your Ember-Data models.","archived":false,"fork":false,"pushed_at":"2024-11-21T15:59:58.000Z","size":8722,"stargazers_count":168,"open_issues_count":14,"forks_count":35,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-04-01T00:34:56.719Z","etag":null,"topics":["ember","ember-addon","ember-cli","ember-data","emberjs","javascript","validator"],"latest_commit_sha":null,"homepage":"http://esbanarango.github.io/ember-model-validator/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/esbanarango.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-05-13T00:14:59.000Z","updated_at":"2025-02-15T09:20:26.000Z","dependencies_parsed_at":"2024-06-18T15:20:01.983Z","dependency_job_id":"c88847e1-253d-49f5-b6db-1e60a2f622ce","html_url":"https://github.com/esbanarango/ember-model-validator","commit_stats":{"total_commits":603,"total_committers":26,"mean_commits":"23.192307692307693","dds":0.451077943615257,"last_synced_commit":"034bd2f27e1e0f965b11ff12605ce8b5703f6add"},"previous_names":[],"tags_count":58,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/esbanarango%2Fember-model-validator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/esbanarango%2Fember-model-validator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/esbanarango%2Fember-model-validator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/esbanarango%2Fember-model-validator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/esbanarango","download_url":"https://codeload.github.com/esbanarango/ember-model-validator/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247761051,"owners_count":20991531,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ember","ember-addon","ember-cli","ember-data","emberjs","javascript","validator"],"created_at":"2024-08-04T01:01:08.454Z","updated_at":"2025-04-08T01:35:34.824Z","avatar_url":"https://github.com/esbanarango.png","language":"JavaScript","funding_links":[],"categories":["Packages"],"sub_categories":["Data validation"],"readme":"# Ember model validator\n\n![Download count all time](https://img.shields.io/npm/dt/ember-model-validator.svg) [![CI](https://github.com/esbanarango/ember-model-validator/actions/workflows/ci.yml/badge.svg)](https://github.com/esbanarango/ember-model-validator/actions/workflows/ci.yml) [![Ember Observer Score](http://emberobserver.com/badges/ember-model-validator.svg)](http://emberobserver.com/addons/ember-model-validator)\n\n### [Live demo \u0026 Documentation](http://esbanarango.github.io/ember-model-validator/)\n\nAdd validations to your _Ember Data_ models on an explicit and easy way, without a bunch a validations files around or complicated structure.\n\nThis README outlines the details of collaborating on this Ember addon.\n\n## Purpose\n\nThis 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.\n\n## Installation\n\nInstall **Ember-model-validator** is easy as:\n\n`npm install ember-model-validator --save-dev`\nor\n`yarn add ember-model-validator --dev`\n\n## Usage\n\n**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).\n\nBy 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**.\n\nYou can also pass an _option_ hash for excluding or forcing certain attributes to be validated, and to prevent errors to be added.\n\n```js\n// Using `except`\nmyModel.validate({ except: ['name', 'cellphone'] });\n\n// Using `only`\nmyModel.validate({ only: ['favoriteColor', 'mainstreamCode'] });\n\n// Using `addErrors`\nmyModel.validate({ addErrors: false });\n// ^ This will validate the model but won't add any errors.\n```\n\nTo target specific validations when using `except`/`only`, pass the validations' names along the attribute's name:\n\n```js\n// This runs all validations, except name's presence and length validations and\n// any email validations.\n// Other name validations are still run.\nmyModel.validate({ except: ['name:presence,length', 'email'] });\n```\n\n### Usage Example\n\n```js\nimport Model, { attr } from '@ember-data/model';\nimport { modelValidator } from 'ember-model-validator';\n\n@modelValidator\nexport default class MyModel extends Model {\n  @attr('string') fullName;\n  @attr('string') fruit;\n  @attr('string') favoriteColor;\n\n  validations = {\n    fullName: {\n      presence: true\n    },\n    fruit: {\n      presence: true\n    },\n    favoriteColor: {\n      color: true\n    }\n  };\n}\n```\n\nAfter setting the validations on your model you will be able to:\n\n```js\nimport Controller from '@ember/controller';\nimport { action } from '@ember/object';\n\nexport default class MyController extends Controller {\n  @action\n  async saveFakeModel() {\n    const fakeModel = this.model;\n\n    if (fakeModel.validate()) {\n      await fakeModel.save();\n    } else {\n      console.log({ errors: fakeModel.get('errors') });\n    }\n  }\n}\n```\n\n### Or Usage in non Model(Controller, Componente, Object ...) Example\n\n```js\nimport Component from '@ember/component';\nimport { objectValidator } from 'ember-model-validator';\n\n@objectValidator\nexport default class MyComponent extends Component {\n  test = 'ABC',\n\n  validations = {\n    test: {\n      presence: true\n    }\n  }\n};\n```\n\n### TypeScript\n```typescript\nimport Model, { attr } from '@ember-data/model';\n\nimport { modelValidator, type ValidationsConfig, type ValidatedModel } from 'ember-model-validator';\n\n// https://github.com/microsoft/TypeScript/issues/4881\ninterface MyModel extends ValidatedModel, Model {}\n\n@modelValidator\nclass MyModel extends Model {\n  @attr('string') declare name: string;\n\n  validations: ValidationsConfig = {\n    name: {\n      presence: true,\n    },\n    email: {\n      presence: true,\n      email: true,\n    },\n  };\n}\n\nexport default MyModel;\n\ndeclare module 'ember-data/types/registries/model' {\n  export default interface ModelRegistry {\n    'my-model': MyModel;\n  }\n}\n\n```\n\n\n## Compatibility\n\n- `ember-source`and `ember-data` v3.28 or above\n\n---\n\n- [Ember model validator](#ember-model-validator)\n    - [Live demo \\\u0026 Documentation](#live-demo--documentation)\n  - [Purpose](#purpose)\n  - [Installation](#installation)\n  - [Usage](#usage)\n    - [Usage Example](#usage-example)\n    - [Or Usage in non Model(Controller, Componente, Object ...) Example](#or-usage-in-non-modelcontroller-componente-object--example)\n    - [TypeScript](#typescript)\n  - [Compatibility](#compatibility)\n  - [Validators](#validators)\n        - [Common options](#common-options)\n    - [Presence](#presence)\n    - [Acceptance](#acceptance)\n    - [Absence](#absence)\n    - [Format](#format)\n    - [Length](#length)\n        - [Options](#options)\n    - [Email](#email)\n    - [ZipCode](#zipcode)\n        - [Options](#options-1)\n    - [Hex Color](#hex-color)\n    - [Subdomain](#subdomain)\n    - [URL](#url)\n    - [Inclusion](#inclusion)\n    - [Exclusion](#exclusion)\n    - [Match](#match)\n        - [Options](#options-2)\n    - [Numericality](#numericality)\n        - [Options](#options-3)\n    - [Date](#date)\n        - [Options](#options-4)\n    - [Custom](#custom)\n    - [Password](#password)\n    - [Relations](#relations)\n    - [Using function to generate custom message](#using-function-to-generate-custom-message)\n        - [Example](#example)\n  - [I18n](#i18n)\n  - [Running Tests](#running-tests)\n\n## Validators\n\n##### Common options\n\nAll validators accept the following options\n\n- `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.\n- `errorAs` _option_. Sets the _key_ name to be used when adding errors (default to property name).\n- `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.\n- `if` _option_. Validates **only** when the function passed returns true. `function(key,value, _this){...}`.\n\n### Presence\n\nA 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.\n\n```js\nvalidations = {\n  name: {\n    presence: true;\n  }\n}\n```\n\n### Acceptance\n\nThese values: `['1', 1, true]` are the acceptable values. But you can specify yours with the `accept` option.\n\n```js\nvalidations = {\n  acceptConditions: {\n    acceptance: {\n      accept: 'yes';\n    }\n  }\n}\n```\n\n\u003e The `accept` option receives either a string or an array of acceptable values.\n\n### Absence\n\nValidates that the specified attributes are absent. It uses [Ember.isPresent](https://emberjs.com/api/ember/3.0/functions/@ember%2Futils/isPresent) method.\n\n```js\nvalidations = {\n  login: {\n    absence: true;\n  }\n}\n```\n\n### Format\n\nSpecify 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.\n\n```js\n  validations = {\n    legacyCode:{\n      format: { with: /^[a-zA-Z]+$/ }\n    }\n  }\n```\n\n### Length\n\nSpecify the lengths that are allowed.\n\n##### Options\n\n- A `number`. The exact length of the value allowed (Alias for `is`).\n- An `array`. Will expand to `minimum` and `maximum`. First element is the lower bound, second element is the upper bound.\n- `is` _option_. The exact length of the value allowed.\n- `minimum` _option_. The minimum length of the value allowed.\n- `maximum` _option_. The maximum length of the value allowed.\n\n```js\n  validations = {\n    socialSecurity: {\n      length: 5\n    },\n    nsaNumber: {\n      length: [3, 5]\n    },\n    chuncaluchoNumber: {\n      length: { is: 10, message: 'this is not the length of a chuncalucho' }\n    },\n    hugeName:{\n      length: {\n        minimum: 3,\n        maximum: 5\n      }\n    },\n    smallName:{\n      length: {\n        maximum: {\n          value: 3,\n          message: 'should be smaller'\n        }\n      }\n    }\n  }\n```\n\n### Email\n\nValidates the proper format of the email.\n\n```js\n  validations = {\n    email: {\n      email: true\n    }\n  }\n```\n\n### ZipCode\n\nThe value must be a correct zipcode. The `countryCode` is optional and defaults to 'US'.\n\nCountries supported and regular expressions used can be found in [postal-codes-regex.js](addon/postal-codes-regex.js)\n\n##### Options\n\n- `countryCode` _option_. The code of the country for which the postal code will be validated.\n\n```js\nvalidations = {\n  postalCode: {\n    // If no countryCode is specified, 'US' is used as default\n    zipCode: true;\n  }\n}\n```\n\n```js\nvalidations = {\n  postalCodeUK: {\n    zipCode: {\n      countryCode: 'UK';\n    }\n  }\n}\n```\n\n### Hex Color\n\nThe value must be a correct Hexadecimal color.\n\n```js\nvalidations = {\n  favoriteColor: {\n    color: true;\n  }\n}\n```\n\n### Subdomain\n\nThe value must a well formatted subdomain. Here you can also specify reserved words.\n\n```js\nvalidations = {\n  mySubdomain: {\n    subdomain: {\n      reserved: ['admin', 'blog'];\n    }\n  }\n}\n```\n\n### URL\n\nThe value must a well formatted URL.\n\n```js\nvalidations = {\n  myBlog: {\n    URL: true;\n  }\n}\n```\n\n### Inclusion\n\nThe value has to be included in a given set.\n\n```js\n  validations = {\n    name:{\n      inclusion: { in: ['Jose Rene', 'Aristi Gol', 'Armani'] }\n    }\n  }\n```\n\n### Exclusion\n\nThe value can't be included in a given set.\n\n```js\n  validations = {\n    name:{\n      exclusion: { in: ['Gionvany Hernandez', 'Wilder Medina'] }\n    }\n  }\n```\n\n### Match\n\nSpecify the attribute to match with.\n\n##### Options\n\n- A `string`. The name of the attribute to match with (Alias for `attr`).\n- `attr` _option_. The name of the attribute to match with.\n\n```js\n  validations = {\n    email:{\n      match: 'confirmationEmail'\n    },\n    password:{\n      match: {\n        attr: 'passwordConfirmation',\n        message: 'sup, it is not the same!'\n      }\n    }\n  }\n```\n\n### Numericality\n\nThe value has to have only numeric values.\n\n##### Options\n\n- `onlyInteger` _option_. The value must be an integer.\n- `greaterThan` _option_. The value must be greater than the supplied value.\n- `greaterThanOrEqualTo` _option_. The value must be greater or equal to the supplied value.\n- `equalTo` _option_. The value must be equal to the supplied value.\n- `lessThan` _option_. The value must be less than the supplied value.\n- `lessThanOrEqualTo` _option_. The value must be less or equal to the supplied value.\n- `odd` _option_. The value must be odd.\n- `even` _option_. The value must be even.\n\n```js\nvalidations = {\n  lotteryNumber: {\n    numericality: true;\n  }\n}\n```\n\n### Date\n\nThe value must be a `Date` object or a string that produces a valid date when passed to the `Date` constructor.\n\n##### Options\n\n- `before` _option_. The value must be before the supplied date.\n- `after` _option_. The value must be after the supplied date.\n\n```js\n  validations = {\n    birthDate: {\n      date: {\n        before: new Date()\n      }\n    },\n    signupDate: {\n      date: {\n        after: '2015-01-01'\n      }\n    }\n  }\n```\n\n### Custom\n\nDefine 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.\n\n```js\n  validations = {\n    lotteryNumber: {\n      custom: function(key, value, model){\n        return model.get('accountBalance') \u003e 1 ? true : false;\n      }\n    }\n  }\n```\n\nthis has the same action as above except will use a custom message instead of the default.\n\n```js\n  validations = {\n    lotteryNumber: {\n      custom: {\n        validation: function(key, value, model){\n          return model.get('accountBalance') \u003e 1 ? true : false;\n        },\n        message: 'You can\\'t win off of good looks and charm.'\n      }\n    }\n  }\n```\n\nto have multiple custom validation functions on the same property, give 'custom' an array of either of the two syntax above.\n\n```js\nvalidations = {\n  lotteryNumber: {\n    custom: [\n      {\n        validation: function(key, value, model) {\n          return model.get('accountBalance') \u003e 1 ? true : false;\n        },\n        message: \"You can't win off of good looks and charm.\"\n      },\n      {\n        validation: function(key, value, model) {\n          return model.get('accountBalance') \u003e 1 ? true : false;\n        },\n        message: \"You can't win off of good looks and charm.\"\n      }\n    ];\n  }\n}\n```\n\n### Password\n\nA 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!\n\n- `mustContainCapital` (capital case character).\n- `mustContainLower` (lower case character).\n- `mustContainNumber`\n- `mustContainSpecial`\n- `length` (explained in-depth [above](#length)).\n\n```js\nvalidations = {\n  password: {\n    presence: true,\n    mustContainCapital: true,\n    mustContainLower: true,\n    mustContainNumber: true,\n    mustContainSpecial: {\n      message: 'One of these characters is required: %@',\n      acceptableChars: '-+_!@#$%^\u0026*.,?()'\n    },\n    length: {\n      minimum: 6\n    }\n  },\n  someOtherThing: {\n    mustContainSpecial: true\n  }\n}\n```\n\n### Relations\n\nThis validator will run the `validate()` function for the specific relation. If it's a `DS.hasMany` relation then it will loop through all objects.\n\n\u003e Note: The relations **have** to be [`embedded`](http://emberjs.com/api/data/classes/DS.EmbeddedRecordsMixin.html) or the promise has to be already resolved.\n\n```js\n  validations = {\n    myHasManyRelation:{\n      relations: ['hasMany']\n    },\n    myBelongsToRelation:{\n      relations: ['belongsTo']\n    }\n  }\n```\n\n### Using function to generate custom message\n\nYou can pass a function to generate a more specific error message. Some scenarios are:\n\n- When the message varies depending of the attribute value.\n- When you want to use model attributes in the message.\n\nThe message function receives the attribute name, the value of the attribute and the model itself.\n\n**NOTE:** If the function doesn't return a string the default message is going to be used.\n\n##### Example\n\n```js\nimport Model, { attr } from '@ember-data/model';\nimport { modelValidator } from 'ember-model-validator';\n\n@modelValidator\nexport default class MyModel extends Model {\n  @attr('number', { defaultValue: 12345 }) otherCustomAttribute;\n\n  validations = {\n    otherCustomAttribute: {\n      custom: {\n        validation: function(key, value) {\n          return value.toString().length === 5 ? true : false;\n        },\n        message: function(key, value, _this) {\n          return key + ' must have exactly 5 digits';\n        }\n      }\n    }\n  };\n}\n```\n\n## I18n\n\nSet `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';\n\n```js\n//config/environment.js\n...\n  ENV:{\n    ...\n    APP:{\n      validatorDefaultLocale: 'pt-br'\n    }\n    ...\n  }\n...\n```\n\n## Running Tests\n\n- `npm test` (Runs `ember try:each` to test your addon against multiple Ember versions)\n- `ember test`\n- `ember test --server`\n\nSee the [Contributing](CONTRIBUTING.md) guide for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fesbanarango%2Fember-model-validator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fesbanarango%2Fember-model-validator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fesbanarango%2Fember-model-validator/lists"}