This post is a living, work in process documentation to give others an idea how things are working so far and how they can help with contributing (or how they can write their own validation library if they would like.
Validation is comprised of five major components. To see the interfaces for each component take a look at aurelia-validation - https://github.com/aurelia/validation
The index of any plugin is where it should implement a configure method. This is where you can do any setup. aurelia-validatejs uses the index.js to register handlers to override the base implementation when the developer imports
ValidationReporter or a
Currently the validation engine is only in charge of finding and returning the proper ValidationReporter. This allows us to get the proper validation reporter instance for our model from anywhere in our codebase.
The validation error is an interface for what a validation error should look like. In aurelia-validatejs you can see we iterate over the properties of the object and transform them to match the interface. This keeps our errors consistent so that they could be provided by any form of validation.
The validation reporter is used to allow anyone to subscribe to errors that are reported on an object. This gives us the ability to show validation errors anywhere in our application, once we have access to the proper reporter instance.
aurelia-validatejs implements an observer that has a dispose method. This means when you
.subscribe() to the reporter an observer is added to the list of
__callbacks__. This is so when the
.publish() method is called, we iterate over all of the callbacks and publish changes to those subscribers.
A validation reporter is nice because it doesn't directly tie our code to error reporting by tacking on properties to the object. It uses a metadata approach.
The validator is the alternative approach to validation. We are building the fluent API for validation to use the validator so that validation can be manually triggered as well.
We also have a few non-standard classes that are specific to aurelia-validatejs.
The validation rules are how aurelia-validatejs implements validate.js. Each rule is represents a form of validation that will be tested against on the property of an object. For example, each of the decorators currently has a rule backing it. For
required we use the
RequiredRule which creates a new validation rule.
The rule takes in a name and a config object. The config object is used by rqeuire.js to configure the validator.
TODO: Give some concreate examples here
The validation config is the interface that is used to keep all of the validation rules as well actually validate the target. When the
.validate() method is called on the config (for example on the setter in
rules/base.js) it validates the entire object. If you only wanted to validate and return errors for one property of the object you would pass in a second optional parameter with the name of the property.
The validation config is fetched from metadata using the
getOrCreateOwn method from aurelia-metadata. This allows the config to exist and be shared or grabbed from anywhere in the application.
Right now all of the rules are in the rules directory. They are implemented through decorators in the
decorators.js. Each of the decorators calls the
base function from
base.js. This adds a getter and a setter on to the object for each of the properties being validated. When the setter is called it grabs the validation reporter and config and calls validate on the object.
To keep it simple and not worry about maintaining a cache of validated properties we validate all properties on the object. This ensures that all of the releveant properties are validated to handle things like dependencies and equality.