# Angular Reactive Validation Reactive Forms validation shouldn't require the developer to write lots of HTML to show validation messages. This library makes it easy. ## Table of contents * [Installation](#installation) * [Compatibility](#compatibility) * [Basic usage](#basic-usage) * [Advanced validation declaration](#advanced-validation-declaration) * [Changing when validation messages are displayed](#changing-when-validation-messages-are-displayed) * [Declaring your own validator functions](#declaring-your-own-validator-functions) * [Edge use cases](#edge-use-cases) * [Handling custom HTML validation messages](#handling-custom-html-validation-messages) * [Using arv-validation-messages when not using `[formGroup]` or `formGroupName` attributes](#using-arv-validation-messages-when-not-using-formgroup-or-formgroupname-attributes) ## Installation To install this library, run: ```bash npm install angular-reactive-validation --save ``` ## Compatibility | Angular version | Package version | |-----------------|-----------------| | 17 | 11.x | | 16 | 10.x | | 15 | 9.x | | 14 | 8.x | ## Basic usage Import the `ReactiveValidationModule`: ```ts import { ReactiveValidationModule } from 'angular-reactive-validation'; @NgModule({ imports: [ ..., ReactiveValidationModule ] }) export class AppModule { } ``` Declare your validation with messages: ```ts import { Validators } from 'angular-reactive-validation'; ... form = this.fb.group({ name: this.fb.group({ firstName: ['', [Validators.required('A first name is required'), Validators.minLength(1, minLength => `The minimum length is ${minLength}`), Validators.maxLength(50, maxLength => `Maximum length is ${maxLength}`)]], middleName: ['', [Validators.maxLength(50, maxLength => `Maximum length is ${maxLength}`)]], lastName: ['', [Validators.required('A last name is required'), Validators.maxLength(50, maxLength => `Maximum length is ${maxLength}`)]] }), age: [null, [ Validators.required('An age is required'), Validators.min(0, 'You can\'t be less than zero years old.'), Validators.max(150, max => `Can't be more than ${max}`) ]] }); ``` See [Advanced validation declaration](#advanced-validation-declaration) for other ways to declare your validation. Add the component that will display the messages to your HTML: ```html ``` Make changes to the styling of the validation messages when needed by using the `invalid-feedback` class. E.g.: ```scss .invalid-feedback { width: 100%; margin-top: .25rem; font-size: 80%; color: red; } ``` ## Advanced validation declaration The library supports specifying validators in a number of ways: With a static message: ```ts Validators.minLength(1, 'The minimum length is not reached.') ``` With a dynamic message, which is passed the validation value: ```ts Validators.minLength(1, minLength => `The minimum length is ${minLength}.`) ``` With a dynamic validation value: ```ts Validators.minLength(() => this.getMinimumLength(), 'The minimum length is not reached.') ``` Or combining the two options above: ```ts Validators.minLength(() => this.getMinimumLength(), minLength => `The minimum length is ${minLength}.`) ``` ## Changing when validation messages are displayed By default validation messages are displayed when the associated control is touched, or when the form has been submitted while the `arv-validation-messages` component was instantiated (meaning any hidden elements would not show their validation until a resubmit). This implementation can be overridden by changing the module import as follows: ```ts import { ReactiveValidationModule } from 'angular-reactive-validation'; @NgModule({ imports: [ ..., ReactiveValidationModule.forRoot({ displayValidationMessageWhen: (control, formSubmitted) => { return true; // Replace with your implementation. } }) ] }) export class AppModule { } ``` Note that `formSubmitted` can be undefined when it's not known if the form is submitted, due to the form tag missing a formGroup attribute. ## Declaring your own validator functions Angular provides a limited set of validator functions. To declare your own validator functions _and_ combine it with this library use the `ValidatorDeclaration` class. It supports declaring validators with zero, one or two arguments. **Note** that if your validator doesn't return an object as the inner error result, but e.g. a `boolean` such as in the examples below, then this will be replaced by an object that can hold the validation message. Thus, in the first example below `{ 'hasvalue': true }` becomes `{ 'hasvalue': { 'message': 'validation message' } }`. ```ts const hasValueValidator = ValidatorDeclaration.wrapNoArgumentValidator(control => { return !!control.value ? null : { 'hasvalue': true }; }, 'hasvalue'); const formControl = new FormControl('', hasValueValidator('error message to show')); ``` ```ts const minimumValueValidator = ValidatorDeclaration.wrapSingleArgumentValidator((min: number) => { return function(control: AbstractControl): ValidationErrors { return control.value >= min ? null : { 'min': true }; }; }, 'min'); const formControl = new FormControl('', minimumValueValidator(5, 'error message to show')); ``` ```ts const betweenValueValidator = ValidatorDeclaration.wrapTwoArgumentValidator((min: number, max: number) => { return function(control: AbstractControl): ValidationErrors { return control.value >= min && control.value <= max ? null : { 'between': true }; }; }, 'between'); const formControl = new FormControl('', betweenValueValidator(5, 10, 'error message to show')); ``` Wrapping validator functions provided by other packages is also very simple: ```ts const minValidator = ValidatorDeclaration.wrapSingleArgumentValidator(AngularValidators.min, 'min') ``` ## Edge use cases ### Handling custom HTML validation messages Though not the purpose of this library. There might be times when you want to declare a validation message within your HTML, because it requires some custom formatting. Therefore, all the `Validators` can also be used without declaring a message: ```ts Validators.minLength(() => this.getMinimumLength()) ``` And the following HTML can be used: ```html Your custom validation message HTML for the minimum value validation. ``` If the `arv-validation-messages`'s `for` attribute specifies multiple controls, be sure to declare the `for` attribute on the `arv-validation-message` element as well: ```html Your custom validation message HTML for the required validation. Your custom validation message HTML for the minlength validation. ``` Note that unlike the default Angular validation, parameterless functions need to be called to work properly: ```ts Validators.required() Validators.requiredTrue() Validators.email() ``` ### Using arv-validation-messages when not using `[formGroup]` or `formGroupName` attributes Supplying FormControl instances instead of names is also supported: ```html ... ```