From 1212b5147f7c142d87aacce6f97fb505b188c8a2 Mon Sep 17 00:00:00 2001 From: Ward Bell Date: Sun, 28 Aug 2016 17:07:13 -0700 Subject: [PATCH] docs(cb-form-validation): add template2 - a step between template and reactive Raises questions about what really separates Forms from ReactiveForms --- .../_examples/cb-form-validation/e2e-spec.ts | 1 + .../ts/app/app.component.ts | 6 +- .../hero-form-reactive.component.html | 30 +- .../reactive/hero-form-reactive.component.ts | 122 ++-- .../app/reactive/hero-form-reactive.module.ts | 2 +- .../ts/app/shared/forbidden-name.directive.ts | 43 ++ .../ts/app/shared/shared.module.ts | 12 +- .../app/template/hero-form-template.module.ts | 9 +- ...tml => hero-form-template1.component.html} | 42 +- ...nt.ts => hero-form-template1.component.ts} | 17 +- .../hero-form-template2.component.html | 52 ++ .../template/hero-form-template2.component.ts | 99 ++++ .../cb-form-validation/ts/index.html | 2 +- .../ts/latest/cookbook/form-validation.jade | 534 +++++++++++++----- .../cookbooks/form-validation/plunker.png | Bin 25379 -> 21082 bytes 15 files changed, 726 insertions(+), 245 deletions(-) create mode 100644 public/docs/_examples/cb-form-validation/ts/app/shared/forbidden-name.directive.ts rename public/docs/_examples/cb-form-validation/ts/app/template/{hero-form-template.component.html => hero-form-template1.component.html} (60%) rename public/docs/_examples/cb-form-validation/ts/app/template/{hero-form-template.component.ts => hero-form-template1.component.ts} (71%) create mode 100644 public/docs/_examples/cb-form-validation/ts/app/template/hero-form-template2.component.html create mode 100644 public/docs/_examples/cb-form-validation/ts/app/template/hero-form-template2.component.ts diff --git a/public/docs/_examples/cb-form-validation/e2e-spec.ts b/public/docs/_examples/cb-form-validation/e2e-spec.ts index 5e68d6e657..60fe5ae0f3 100644 --- a/public/docs/_examples/cb-form-validation/e2e-spec.ts +++ b/public/docs/_examples/cb-form-validation/e2e-spec.ts @@ -1,4 +1,5 @@ /// +'use strict'; // necessary for node! describeIf(browser.appIsTs || browser.appIsJs, 'Forms Tests', function () { beforeEach(function () { diff --git a/public/docs/_examples/cb-form-validation/ts/app/app.component.ts b/public/docs/_examples/cb-form-validation/ts/app/app.component.ts index 5260b8d9e1..2da4dc4d0a 100644 --- a/public/docs/_examples/cb-form-validation/ts/app/app.component.ts +++ b/public/docs/_examples/cb-form-validation/ts/app/app.component.ts @@ -3,8 +3,10 @@ import { Component } from '@angular/core'; @Component({ selector: 'my-app', - template: ` + template: `
- ` + +
+ ` }) export class AppComponent { } diff --git a/public/docs/_examples/cb-form-validation/ts/app/reactive/hero-form-reactive.component.html b/public/docs/_examples/cb-form-validation/ts/app/reactive/hero-form-reactive.component.html index 8b7f81f0d7..149537bd3e 100644 --- a/public/docs/_examples/cb-form-validation/ts/app/reactive/hero-form-reactive.component.html +++ b/public/docs/_examples/cb-form-validation/ts/app/reactive/hero-form-reactive.component.html @@ -1,16 +1,19 @@
-

Hero Form (Reactive)

-
+

Hero Form 3 (Reactive)

+ + +
+ -
- {{ formError.name }} + formControlName="name" required > + +
+ {{ formErrors.name }}
@@ -18,28 +21,27 @@
+ formControlName="alterEgo" >
-
- {{ formError.power }} + +
+ {{ formErrors.power }}
+ (click)="addHero()">New Hero
- +
diff --git a/public/docs/_examples/cb-form-validation/ts/app/reactive/hero-form-reactive.component.ts b/public/docs/_examples/cb-form-validation/ts/app/reactive/hero-form-reactive.component.ts index c61d3ef05d..f33d37bb13 100644 --- a/public/docs/_examples/cb-form-validation/ts/app/reactive/hero-form-reactive.component.ts +++ b/public/docs/_examples/cb-form-validation/ts/app/reactive/hero-form-reactive.component.ts @@ -4,104 +4,112 @@ import { Component, OnInit } from '@angular/core'; import { FormGroup, FormBuilder, Validators } from '@angular/forms'; -import { Hero } from '../shared/hero'; +import { Hero } from '../shared/hero'; +import { forbiddenNameValidator } from '../shared/forbidden-name.directive'; @Component({ moduleId: module.id, - selector: 'hero-form-reactive', + selector: 'hero-form-reactive3', templateUrl: 'hero-form-reactive.component.html' }) -// #docregion class export class HeroFormReactiveComponent implements OnInit { powers = ['Really Smart', 'Super Flexible', 'Weather Changer']; - model = new Hero(18, 'Dr. WhatIsHisWayTooLongName', this.powers[0], 'Dr. What'); + hero = new Hero(18, 'Dr. WhatIsHisName', this.powers[0], 'Dr. What'); submitted = false; + // #docregion on-submit onSubmit() { this.submitted = true; - this.model = this.heroForm.value; + this.hero = this.heroForm.value; } -// #enddocregion class + // #enddocregion on-submit +// #enddocregion // Reset the form with a new hero AND restore 'pristine' class state // by toggling 'active' flag which causes the form // to be removed/re-added in a tick via NgIf // TODO: Workaround until NgForm has a reset method (#6822) - // #docregion new-hero active = true; - -// #docregion class - newHero() { - this.model = new Hero(42, '', ''); +// #docregion + // #docregion add-hero + addHero() { + this.hero = new Hero(42, '', ''); this.buildForm(); - this.onValueChanged(''); + this.onValueChanged(); + // #enddocregion add-hero // #enddocregion class this.active = false; setTimeout(() => this.active = true, 0); -// #docregion class +// #docregion + // #docregion add-hero + } + // #enddocregion add-hero + + // #docregion form-builder + heroForm: FormGroup; + constructor(private fb: FormBuilder) { } + + ngOnInit(): void { + this.buildForm(); } - //// New with Reactive Form + buildForm(): void { + this.heroForm = this.fb.group({ + // #docregion name-validators + 'name': [this.hero.name, [ + Validators.required, + Validators.minLength(4), + Validators.maxLength(24), + forbiddenNameValidator(/bob/i) + ] + ], + // #enddocregion name-validators + 'alterEgo': [this.hero.alterEgo], + 'power': [this.hero.power, Validators.required] + }); - heroForm: FormGroup; - constructor(private builder: FormBuilder) { } + this.heroForm.valueChanges + .subscribe(data => this.onValueChanged(data)); + } - ngOnInit(): void { this.buildForm(); } + // #enddocregion form-builder - formError = { + onValueChanged(data?: any) { + const controls = this.heroForm ? this.heroForm.controls : {}; + + for (const field in this.formErrors) { + // clear previous error message (if any) + this.formErrors[field] = ''; + const control = controls[field]; + + if (control && control.dirty && !control.valid) { + const messages = this.validationMessages[field]; + for (const key in control.errors) { + this.formErrors[field] += messages[key] + ' '; + } + } + } + } + + formErrors = { 'name': '', 'power': '' }; validationMessages = { 'name': { - 'required': 'Name is required.', - 'minlength': 'Name must be at least 4 characters long.', - 'maxlength': 'Name cannot be more than 24 characters long.' + 'required': 'Name is required.', + 'minlength': 'Name must be at least 4 characters long.', + 'maxlength': 'Name cannot be more than 24 characters long.', + 'forbiddenName': 'Someone named "Bob" cannot be a hero.' }, 'power': { 'required': 'Power is required.' } }; - - buildForm(): void { - this.heroForm = this.builder.group({ - 'name': [this.model.name, [ - Validators.required, - Validators.minLength(4), - Validators.maxLength(24) - ] - ], - 'alterEgo': [this.model.alterEgo], - 'power': [this.model.power, Validators.required] - }); - this.heroForm.valueChanges - .subscribe(data => this.onValueChanged(data)); - } - - onValueChanged(data: any) { - const controls = this.heroForm ? this.heroForm.controls : {}; - for (const field in this.formError) { - // clear previous error message (if any) - this.formError[field] = ''; - const control = controls[field]; - if (control && control.dirty && !control.valid) { - const messages = this.validationMessages[field]; - for (const key in control.errors) { - this.formError[field] += messages[key] + ' '; - } - } - } - } - - isRequired(controlName: string): boolean { - const msgs = this.validationMessages[controlName]; - return msgs && msgs['required']; - } } -// #enddocregion class // #enddocregion diff --git a/public/docs/_examples/cb-form-validation/ts/app/reactive/hero-form-reactive.module.ts b/public/docs/_examples/cb-form-validation/ts/app/reactive/hero-form-reactive.module.ts index dd9aecda74..6ff9265e92 100644 --- a/public/docs/_examples/cb-form-validation/ts/app/reactive/hero-form-reactive.module.ts +++ b/public/docs/_examples/cb-form-validation/ts/app/reactive/hero-form-reactive.module.ts @@ -2,7 +2,7 @@ import { NgModule } from '@angular/core'; import { ReactiveFormsModule } from '@angular/forms'; -import { SharedModule } from '../shared/shared.module'; +import { SharedModule } from '../shared/shared.module'; import { HeroFormReactiveComponent } from './hero-form-reactive.component'; @NgModule({ diff --git a/public/docs/_examples/cb-form-validation/ts/app/shared/forbidden-name.directive.ts b/public/docs/_examples/cb-form-validation/ts/app/shared/forbidden-name.directive.ts new file mode 100644 index 0000000000..a8f6c03d33 --- /dev/null +++ b/public/docs/_examples/cb-form-validation/ts/app/shared/forbidden-name.directive.ts @@ -0,0 +1,43 @@ +// #docregion +import { Directive, Input, OnChanges, SimpleChanges } from '@angular/core'; +import { AbstractControl, NG_VALIDATORS, Validator, ValidatorFn, Validators } from '@angular/forms'; + +// #docregion custom-validator +/** A hero's name can't match the given regular expression */ +export function forbiddenNameValidator(nameRe: RegExp): ValidatorFn { + return (control: AbstractControl): {[key: string]: any} => { + const name = control.value; + const no = nameRe.test(name); + return no ? {'forbiddenName': {name}} : null; + }; +} +// #enddocregion custom-validator + +// #docregion directive +@Directive({ + selector: '[forbiddenName]', + // #docregion directive-providers + providers: [{provide: NG_VALIDATORS, useExisting: ForbiddenValidatorDirective, multi: true}] + // #enddocregion directive-providers +}) +export class ForbiddenValidatorDirective implements Validator, OnChanges { + @Input() forbiddenName: string; + private valFn = Validators.nullValidator; + + ngOnChanges(changes: SimpleChanges): void { + const change = changes['forbiddenName']; + if (change) { + const val: string | RegExp = change.currentValue; + const re = val instanceof RegExp ? val : new RegExp(val, 'i'); + this.valFn = forbiddenNameValidator(re); + } else { + this.valFn = Validators.nullValidator; + } + } + + validate(control: AbstractControl): {[key: string]: any} { + return this.valFn(control); + } +} +// #docregion directive + diff --git a/public/docs/_examples/cb-form-validation/ts/app/shared/shared.module.ts b/public/docs/_examples/cb-form-validation/ts/app/shared/shared.module.ts index fd6c35ef2e..2b0ada59bd 100644 --- a/public/docs/_examples/cb-form-validation/ts/app/shared/shared.module.ts +++ b/public/docs/_examples/cb-form-validation/ts/app/shared/shared.module.ts @@ -1,12 +1,14 @@ // #docregion -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; -import { SubmittedComponent } from './submitted.component'; +import { ForbiddenValidatorDirective } from './forbidden-name.directive'; +import { SubmittedComponent } from './submitted.component'; @NgModule({ imports: [ CommonModule], - declarations: [ SubmittedComponent ], - exports: [ CommonModule, SubmittedComponent ] + declarations: [ ForbiddenValidatorDirective, SubmittedComponent ], + exports: [ ForbiddenValidatorDirective, SubmittedComponent, + CommonModule ] }) export class SharedModule { } diff --git a/public/docs/_examples/cb-form-validation/ts/app/template/hero-form-template.module.ts b/public/docs/_examples/cb-form-validation/ts/app/template/hero-form-template.module.ts index 800ba19643..042c019d5e 100644 --- a/public/docs/_examples/cb-form-validation/ts/app/template/hero-form-template.module.ts +++ b/public/docs/_examples/cb-form-validation/ts/app/template/hero-form-template.module.ts @@ -2,12 +2,13 @@ import { NgModule } from '@angular/core'; import { FormsModule } from '@angular/forms'; -import { SharedModule } from '../shared/shared.module'; -import { HeroFormTemplateComponent } from './hero-form-template.component'; +import { SharedModule } from '../shared/shared.module'; +import { HeroFormTemplate1Component } from './hero-form-template1.component'; +import { HeroFormTemplate2Component } from './hero-form-template2.component'; @NgModule({ imports: [ SharedModule, FormsModule ], - declarations: [ HeroFormTemplateComponent ], - exports: [ HeroFormTemplateComponent ] + declarations: [ HeroFormTemplate1Component, HeroFormTemplate2Component ], + exports: [ HeroFormTemplate1Component, HeroFormTemplate2Component ] }) export class HeroFormTemplateModule { } diff --git a/public/docs/_examples/cb-form-validation/ts/app/template/hero-form-template.component.html b/public/docs/_examples/cb-form-validation/ts/app/template/hero-form-template1.component.html similarity index 60% rename from public/docs/_examples/cb-form-validation/ts/app/template/hero-form-template.component.html rename to public/docs/_examples/cb-form-validation/ts/app/template/hero-form-template1.component.html index 575036701e..22b374b622 100644 --- a/public/docs/_examples/cb-form-validation/ts/app/template/hero-form-template.component.html +++ b/public/docs/_examples/cb-form-validation/ts/app/template/hero-form-template1.component.html @@ -1,28 +1,30 @@
-

Hero Form (Template-Driven)

-
+

Hero Form 1 (Template)

+ + +
+ +
-
- Name is required -
-
- Name must be at least 4 characters long. -
-
- Name cannot be more than 24 characters long. -
+
+ Name is required +
+
+ Name must be at least 4 characters long. +
+
+ Name cannot be more than 24 characters long. +
@@ -30,17 +32,19 @@
+ name="alterEgo" + [(ngModel)]="hero.alterEgo" >
+
Power is required
@@ -49,9 +53,9 @@ + (click)="addHero()">New Hero
- +
diff --git a/public/docs/_examples/cb-form-validation/ts/app/template/hero-form-template.component.ts b/public/docs/_examples/cb-form-validation/ts/app/template/hero-form-template1.component.ts similarity index 71% rename from public/docs/_examples/cb-form-validation/ts/app/template/hero-form-template.component.ts rename to public/docs/_examples/cb-form-validation/ts/app/template/hero-form-template1.component.ts index 9149ad3126..845fcc9abc 100644 --- a/public/docs/_examples/cb-form-validation/ts/app/template/hero-form-template.component.ts +++ b/public/docs/_examples/cb-form-validation/ts/app/template/hero-form-template1.component.ts @@ -8,15 +8,15 @@ import { Hero } from '../shared/hero'; @Component({ moduleId: module.id, - selector: 'hero-form-template', - templateUrl: 'hero-form-template.component.html' + selector: 'hero-form-template1', + templateUrl: 'hero-form-template1.component.html' }) // #docregion class -export class HeroFormTemplateComponent { +export class HeroFormTemplate1Component { powers = ['Really Smart', 'Super Flexible', 'Weather Changer']; - model = new Hero(18, 'Dr. WhatIsHisWayTooLongName', this.powers[0], 'Dr. What'); + hero = new Hero(18, 'Dr. WhatIsHisWayTooLongName', this.powers[0], 'Dr. What'); submitted = false; @@ -24,20 +24,23 @@ export class HeroFormTemplateComponent { this.submitted = true; } // #enddocregion class - +// #enddocregion // Reset the form with a new hero AND restore 'pristine' class state // by toggling 'active' flag which causes the form // to be removed/re-added in a tick via NgIf // TODO: Workaround until NgForm has a reset method (#6822) active = true; +// #docregion // #docregion class - newHero() { - this.model = new Hero(42, '', ''); + addHero() { + this.hero = new Hero(42, '', ''); // #enddocregion class +// #enddocregion this.active = false; setTimeout(() => this.active = true, 0); +// #docregion // #docregion class } } diff --git a/public/docs/_examples/cb-form-validation/ts/app/template/hero-form-template2.component.html b/public/docs/_examples/cb-form-validation/ts/app/template/hero-form-template2.component.html new file mode 100644 index 0000000000..8bb7066541 --- /dev/null +++ b/public/docs/_examples/cb-form-validation/ts/app/template/hero-form-template2.component.html @@ -0,0 +1,52 @@ + +
+
+

Hero Form 2 (Template & Messages)

+ +
+ +
+ + + + + + + +
+ {{ formErrors.name }} +
+ +
+ +
+ + +
+ +
+ + + +
+ {{ formErrors.power }} +
+
+ + + +
+
+ + +
diff --git a/public/docs/_examples/cb-form-validation/ts/app/template/hero-form-template2.component.ts b/public/docs/_examples/cb-form-validation/ts/app/template/hero-form-template2.component.ts new file mode 100644 index 0000000000..ae6c0367b4 --- /dev/null +++ b/public/docs/_examples/cb-form-validation/ts/app/template/hero-form-template2.component.ts @@ -0,0 +1,99 @@ +/* tslint:disable: member-ordering forin */ +// #docplaster +// #docregion +import { Component, AfterViewChecked, ViewChild } from '@angular/core'; +import { NgForm } from '@angular/forms'; + +import { Hero } from '../shared/hero'; + +@Component({ + moduleId: module.id, + selector: 'hero-form-template2', + templateUrl: 'hero-form-template2.component.html' +}) +export class HeroFormTemplate2Component implements AfterViewChecked { + + powers = ['Really Smart', 'Super Flexible', 'Weather Changer']; + + hero = new Hero(18, 'Dr. WhatIsHisWayTooLongName', this.powers[0], 'Dr. What'); + + submitted = false; + + onSubmit() { + this.submitted = true; + } +// #enddocregion + + // Reset the form with a new hero AND restore 'pristine' class state + // by toggling 'active' flag which causes the form + // to be removed/re-added in a tick via NgIf + // TODO: Workaround until NgForm has a reset method (#6822) + active = true; +// #docregion + + addHero() { + this.hero = new Hero(42, '', ''); +// #enddocregion + + this.active = false; + setTimeout(() => this.active = true, 0); +// #docregion + } + + // #docregion view-child + heroForm: NgForm; + @ViewChild('heroForm') currentForm: NgForm; + + ngAfterViewChecked() { + this.formChanged(); + } + + formChanged() { + if (this.currentForm === this.heroForm) { return; } + this.heroForm = this.currentForm; + if (this.heroForm) { + this.heroForm.valueChanges + .subscribe(data => this.onValueChanged(data)); + } + } + // #enddocregion view-child + + // #docregion handler + onValueChanged(data?: any) { + const controls = this.heroForm ? this.heroForm.controls : {}; + + for (const field in this.formErrors) { + // clear previous error message (if any) + this.formErrors[field] = ''; + const control = controls[field]; + + if (control && control.dirty && !control.valid) { + const messages = this.validationMessages[field]; + for (const key in control.errors) { + this.formErrors[field] += messages[key] + ' '; + } + } + } + } + + formErrors = { + 'name': '', + 'power': '' + }; + // #enddocregion handler + + // #docregion messages + validationMessages = { + 'name': { + 'required': 'Name is required.', + 'minlength': 'Name must be at least 4 characters long.', + 'maxlength': 'Name cannot be more than 24 characters long.', + 'forbiddenName': 'Someone named "Bob" cannot be a hero.' + }, + 'power': { + 'required': 'Power is required.' + } + }; + // #enddocregion messages +} +// #enddocregion diff --git a/public/docs/_examples/cb-form-validation/ts/index.html b/public/docs/_examples/cb-form-validation/ts/index.html index 43a3a70f60..6aea5beaa4 100644 --- a/public/docs/_examples/cb-form-validation/ts/index.html +++ b/public/docs/_examples/cb-form-validation/ts/index.html @@ -8,7 +8,7 @@ - + diff --git a/public/docs/ts/latest/cookbook/form-validation.jade b/public/docs/ts/latest/cookbook/form-validation.jade index ba0e9693de..877026adcc 100644 --- a/public/docs/ts/latest/cookbook/form-validation.jade +++ b/public/docs/ts/latest/cookbook/form-validation.jade @@ -1,198 +1,462 @@ include ../_util-fns - +a#top :marked - We can improve overall data quality by validating user input for accuracy and completeness. + We can improve overall data quality by validating user input for accuracy and completeness. - In this cookbook we show how to validate user input in the UI and display useful validation messages - using first the template-driven forms and then the reactive forms approach. + In this cookbook we show how to validate user input in the UI and display useful validation messages + using first the template-driven forms and then the reactive forms approach. +.l-sub-section + :marked + Learn more about these choices in the [Forms chapter.](../guide/forms.html) - An Angular component consists of a template and a component class containing the code that drives the template. - The first example demonstrates input validation entirely within the template. - The second example moves the validation logic out of the template and into the component class, - giving the developer more control and easier unit testing. - - Both examples are based on the the sample form in the [Forms chapter.](../guide/forms.html) - - +a#toc :marked ## Contents - [Template-Driven Forms Approach](#template-driven) + [Simple Template-Driven Forms](#template1) - [Reactive Forms Approach](#reactive) + [Template-Driven Forms with validation messages in code](#template2) - **Try the live example** - + [Reactive Forms with validation in code](#reactive) + + [Custom validation](#custom-validation) + + [Testing](#testing) + +a#live-example +:marked + **Try the live example to see and download the full cookbook source code** +live-example(name="cb-form-validation" embedded img="cookbooks/form-validation/plunker.png") .l-main-section - +a#template1 :marked - ## Template-Driven Forms + ## Simple Template-Driven Forms - In the template-driven approach, - each control on the form defines its own validation and validation messages in the template. + In the template-driven approach, you arrange + [form elements](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Forms_in_HTML) in the component's template. + You add Angular form directives (mostly directives beginning `ng...`) to help + Angular construct a corresponding internal control model that implements form functionality. + We say that the control model is _implicit_ in the template. + + To validate user input, you add [HTML validation attributes](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5/Constraint_validation) + to the elements. Angular interprets those as well, adding validator functions to the control model. + + Angular exposes information about the state of the controls including + whether the user has "touched" the control or made changes and if the control values are valid. + + In the first template validation example, + we add more HTML to read that control state and update the display appropriately. Here's an excerpt from the template html for a single input box control bound to the hero name: -+makeExample('cb-form-validation/ts/app/template/hero-form-template.component.html','name-with-error-msg','app/template/hero-form-template.component.html (Hero name)') ++makeExample('cb-form-validation/ts/app/template/hero-form-template1.component.html','name-with-error-msg','template/hero-form-template1.component.html (Hero name)')(format='.') :marked Note the following: - - The `` element implements the validation rules as HTML validation attributes: `required`, `minlength`, and `maxlength`. + - The `` element carries the HTML validation attributes: `required`, `minlength`, and `maxlength`. - - Set the `name` attribute of the input box so Angular can track this input element. + - We set the `name` attribute of the input box to `"name"` so Angular can track this input element and associate it + with an Angular form control called `name` in its internal control model. - - The `[(ngModel)]` two-way data binding to the hero's name in the `model.name` property also - registers the input box as a control associated with the implicit `NgForm` directive. + - We use the `[(ngModel)]` directive to two-way data bind the input box to the `hero.name` property. - - A template variable (`#name`) is a reference to this control. - that we can check for control states such as `valid` or `dirty`. - The template variable value is always `ngModel`. + - We set a template variable (`#name`) to the value `"ngModel"` (always `ngModel`). + This gives us a reference to the Angular `NgModel` directive + associated with this control that we can use _in the template_ + to check for control states such as `valid` and `dirty`. - - A `
` element for a group of validation error messages. - The `*ngIf` reveals the error group if there are any errors and + - The `*ngIf` on `
` element reveals a set of nested message `divs` but only if there are "name" errors and the control is either `dirty` or `touched`. - - Within the error group are separate `
` elements for each possible validation error. - Here we've prepared messages for `required`, `minlength`, and `maxlength`. + - Each nested `
` can present a custom message for one of the possible validation errors. + We've prepared messages for `required`, `minlength`, and `maxlength`. The full template repeats this kind of layout for each data entry control on the form. .l-sub-section :marked + #### Why check _dirty_ and _touched_? + We shouldn't show errors for a new hero before the user has had a chance to edit the value. The checks for `dirty` and `touched` prevent premature display of errors. Learn about `dirty` and `touched` in the [Forms](../guide/forms.html) chapter. :marked - The component class manages the hero model used in the data binding - as well as other code to support the view. + The component class manages the hero model used in the data binding + as well as other code to support the view. -+makeExample('cb-form-validation/ts/app/template/hero-form-template.component.ts','class','app/template/hero-form-template.component.ts') ++makeExample('cb-form-validation/ts/app/template/hero-form-template1.component.ts','class','template/hero-form-template1.component.ts (class)') :marked - Use this template-driven validation technique when working with simple forms with simple validation scenarios. + Use this template-driven validation technique when working with static forms with simple, standard validation rules. - Here are the pertinent files for the template-driven approach: + Here are the complete files for the first version of `HeroFormTemplateCompononent` in the template-driven approach: -+makeTabs( - `cb-form-validation/ts/app/template/hero-form-template.module.ts, - cb-form-validation/ts/app/template/hero-form-template.component.html, - cb-form-validation/ts/app/template/hero-form-template.component.ts, - cb-form-validation/ts/app/shared/hero.ts, - cb-form-validation/ts/app/shared/submitted.component.ts`, ++makeTabs( + `cb-form-validation/ts/app/template/hero-form-template1.component.html, + cb-form-validation/ts/app/template/hero-form-template1.component.ts`, '', - `app/template/hero-form-template.module.ts, - app/template/hero-form-template.component.html, - app/template/hero-form-template.component.ts, - app/shared/hero.ts, - app/shared/submitted.component.ts`) + `template/hero-form-template1.component.html, + template/hero-form-template1.component.ts`) .l-main-section - +a#template2 :marked - ## Reactive Forms + ## Template-Driven Forms with validation messages in code - Reactive forms are an alternate approach to form validation in the validation rules are specified in the model as - defined in the component class. Defining the validation in the class instead of the template gives you more control. - You can adjust the validation based on the application state or user. - Your code then becomes the source of truth for your validation. + While the layout is straightforward, + there are obvious shortcomings with the way we handle validation messages: - We also remove the data binding (`ngModel`) and validation messages from the template. - This means that we need to set the default value for each control, and we need to add code - that tracks the user's changes so we can hide/show validation messages as needed. + * It takes a lot of HTML to represent all possible error conditions. + This gets out of hand when there are many controls and many validation rules. + + * We're not fond of so much JavaScript logic in HTML. -.alert.is-important + * The messages are static strings, hard-coded into the template. + We often require dynamic messages that we should shape in code. + + We can move the logic and the messages into the component with a few changes to + the template and component. + + Here's the hero name again, excerpted from the revised template ("Template 2"), next to the original version: ++makeTabs( + `cb-form-validation/ts/app/template/hero-form-template2.component.html, + cb-form-validation/ts/app/template/hero-form-template1.component.html`, + 'name-with-error-msg, name-with-error-msg', + `hero-form-template2.component.html (name #2), + hero-form-template1.component.html (name #1)`) + +:marked + The `` element HTML is almost the same. There are noteworthy differences: + - The hard-code error message `` are gone. + + - There's a new attribute, `forbiddenName`, that is actually a custom validation directive. + It invalidates the control if the user enters "bob" anywhere in the name ([try it](#live-example)). + We discuss [custom validation directives](#custom-validation) later in this cookbook. + + - The `#name` template variable is gone because we no longer refer to the Angular control for this element. + + - Binding to the new `formErrors.name` property is sufficent to display all name validation error messages. + + #### Component class + The original component code stays the same. + We _added_ new code to acquire the Angular form control and compose error messages. + + The first step is to acquire the form control that Angular created from the template by querying for it. + + Look back at the top of the component template where we set the + `#heroForm` template variable in the `
` element: ++makeExample('cb-form-validation/ts/app/template/hero-form-template1.component.html','form-tag','template/hero-form-template1.component.html (form tag)')(format='.') + +:marked + The `heroForm` variable is a reference to the control model that Angular derived from the template. + We tell Angular to inject that model into the component class's `currentForm` property using a `@ViewChild` query: ++makeExample('cb-form-validation/ts/app/template/hero-form-template2.component.ts','view-child','template/hero-form-template2.component.ts (heroForm)')(format='.') + +:marked + Some observations: + + - Angular `@ViewChild` queries for a template variable when you pass it + the name of that variable as a string (`'heroForm'` in this case). + + - The `heroForm` object changes several times during the life of the component, most notably when we add a new hero. + We'll have to re-inspect it periodically. + + - Angular calls the `ngAfterViewChecked` [lifecycle hook method](../guide/lifecycle-hooks.html#afterview) + when anything changes in the view. + That's the right time to see if there's a new `heroForm` object. + + - When there _is_ a new `heroForm` model, we subscribe to its `valueChanged` _Observable_ property. + The `onValueChanged` handler looks for validation errors after every user keystroke. ++makeExample('cb-form-validation/ts/app/template/hero-form-template2.component.ts','handler','template/hero-form-template2.component.ts (handler)')(format='.') + +:marked + The `onValueChanged` handler interprets user data entry. + The `data` object passed into the handler contains the current element values. + The handler ignores them. Instead, it iterates over the fields of the component's `formErrors` object. + + The `formErrors` is a dictionary of the hero fields that have validation rules and their current error messages. + Only two hero properties have validation rules, `name` and `power`. + The messages are empty strings when the hero data are valid. + + For each field, the handler + - clears the prior error message if any + - acquires the field's corresponding Angular form control + - if such a control exists _and_ its been changed ("dirty") _and_ its invalid ... + - the handler composes a consolidated error message for all of the control's errors. + + We'll need some error messages of course, a set for each validated property, one message per validation rule: ++makeExample('cb-form-validation/ts/app/template/hero-form-template2.component.ts','messages','template/hero-form-template2.component.ts (messages)')(format='.') +:marked + Now every time the user makes a change, the `onValueChanged` handler checks for validation errors and produces messages accordingly. + + ### Is this an improvement? + + Clearly the template got substantially smaller while the component code got substantially larger. + It's not easy to see the benefit when there are just three fields and only two of them have validation rules. + + Consider what happens as we increase the number of validated fields and rules. + In general, HTML is harder to read and maintain than code. + The initial template was already large and threatening to get rapidly worse as we add more validation message ``. + + After moving the validation messaging to the component, + the template grows more slowly and proportionally. + Each field has approximately the same number of lines no matter its number of validation rules. + The component also grows proportionally, at the rate of one line per validated field + and one line per validation message. + + Both trends are manageable. + + Now that the messages are in code, we have more flexibility. We can compose messages more intelligently. + We can refactor the messages out of the component, perhaps to a service class that retrieves them from the server. + In short, there are more opportunities to improve message handling now that text and logic have moved from template to code. + + ### _FormModule_ and template-driven forms + + Angular has two different forms modules — `FormsModule` and `ReactiveFormsModule` — + that correspond with the two approaches to form development. + Both modules come from the same `@angular/forms` library package. + + We've been reviewing the "Template-driven" approach which requires the `FormsModule` + Here's how we imported it in the `HeroFormTemplateModule`. + ++makeExample('cb-form-validation/ts/app/template/hero-form-template.module.ts','','template/hero-form-template.module.ts')(format='.') +.l-sub-section :marked - When moving the validation attributes out of the HTML, we are no longer aria ready. Work is being done to - address this. + We haven't talked about the `SharedModule` or its `SubmittedComponent` which appears at the bottom of every + form template in this cookbook. -+makeExample('cb-form-validation/ts/app/reactive/hero-form-reactive.component.ts','class','app/reactive/hero-form-reactive.component.ts') + They're not germane to the validation story. Look at the [live example](#live-example) if you're interested. + +.l-main-section +a#reactive +:marked + ## Reactive Forms + + In the template-driven approach, you markup the template with form elements, validation attributes, + and `ng...` directives from the Angular `FormsModule`. + At runtime, Angular interprets the template and derives its _form control model_. + + **Reactive Forms** takes a different approach. + You create the form control model in code. You write the template with form elements + and`form...` directives from the Angular `ReactiveFormsModule`. + At runtime, Angular binds the template elements to your control model based on your instructions. + + This approach requires a bit more effort. *You have to write the control model and manage it*. + + In return, you can + * add, change, and remove validation functions on the fly + * manipulate the control model dynamically from within the component + * [test](#testing) validation and control logic with isolated unit tests. + + The third cookbook sample re-writes the hero form in _reactive forms_ style. + + ### Switch to the _ReactiveFormsModule_ + The reactive forms classes and directives come from the Angular `ReactiveFormsModule`, not the `FormsModule`. + The application module for the "Reactive Forms" feature in this sample looks like this: ++makeExample('cb-form-validation/ts/app/reactive/hero-form-reactive.module.ts','','app/reactive/hero-form-reactive.module.ts')(format='.') +:marked + The "Reactive Forms" feature module and component are in the `app/reactive` folder. + Let's focus on the `HeroFormReactiveComponent` there, starting with its template. + + ### Component template + + We begin by changing the `` tag so that it binds the Angular `formGroup` directive in the template + to the `heroForm` property in the component class. + The `heroForm` is the control model that the component class builds and maintains. + ++makeExample('cb-form-validation/ts/app/reactive/hero-form-reactive.component.html','form-tag')(format='.') +:marked + Then we modify the template HTML elements to match the _reactive forms_ style. + Here is the "name" portion of the template again, revised for reactive forms and compared with the template-driven version: ++makeTabs( + `cb-form-validation/ts/app/reactive/hero-form-reactive.component.html, + cb-form-validation/ts/app/template/hero-form-template2.component.html`, + 'name-with-error-msg, name-with-error-msg', + `hero-form-reactive.component.html (name #3), + hero-form-template1.component.html (name #2)`) :marked - In the component's class, we define the form and our own data structures to manage definition and display of the validation messages: - - Declare a property for the form typed as a `FormGroup`. - - Declare a property for a collection that contains the *current* validation messages to display to the user. - We'll initialize this collection with one entry for each control. We'll update this collection - with appropriate validation messages when validation rules are broken. - - Declare a property for a collection that contains the set of *possible* validation messages. We'll initialize - this collection with all of the possible validation messages for each control. - - Add a constructor for the class and use dependency injection to inject in the `FormBuilder` service. We use - that service to build the form. - - In the constructor, initialize the collections. - - The `formError` collection is initialized using the control - name as the key and the current validation message as the value. When the form is first displayed, no validation messages - should appear, so the current validation message for each control is empty. - - The `validationMessages` collection is - initialized using the control name as the key and the set of possible validation messages as the value. For this example, - we hard-code in the set of validation messages. But you can retrieve these messages from an external file or - from a database table. Alternatively, you could build a service that retrieved and managed the set of validation messsages. - - Build a method to create the form. We name this method `buildForm` in our example. - The form is created in a method so it can be - called again to reset the form with different default values when adding a new hero. - - In the `buildForm` method, group the controls defined for the form using the `FormBuilder` instance. Here we define each control's name, default value, and - validation rules. - - We call this `buildForm` method from the `ngOnInit` lifecycle hook method. But in many applications, you may need to call `buildForm` - from somewhere else. For example, if the default values are coming from an http request, call the `buildForm` method - after the data is retrieved. + Key changes: + - the validation attributes are gone (except `required`) because we'll be validating in code. + + - `required` remains, not for validation purposes (we'll cover that in the code), + but rather for css styling and accessibility. .l-sub-section :marked - Learn more about `ngOnInit` in the [LifeCycle Hooks](../guide/lifecycle-hooks.html) chapter. -:marked - There is one more important thing that we need to do. We need to watch for any changes that the user makes and adjust the - validation messages appropriately. For example, if the user enters a single character into the name field, we need to - change the validation message from `Name is required` to `Name must be at least 4 characters long`. And when the user - enters the fourth character, we need to remove the message entirely. + A future version of reactive forms will add the `required` HTML validation attribute to the DOM element + (and perhaps the `aria-required` attribute) when the control has the `required` validator function. - To watch for changes, we add one additional statement to the `buildForm` method. We subscribe to the built-in - `FormGroup`'s `valueChanges` observable. Each time any control on the form is changed by the user, we receive a - notification. In our example, we then call an `onValueChanged` method to reset the validation messages. - - In the `onValueChanged` method, we: - - Loop through each entry in the `formError` collection. - - Determine whether the control has an error using the control's properties and our business rules. In our example - we define that a control has an error if the control is dirty and not valid. - - We clear any prior validation messages. - - If the control has a validation error, we loop through the errors collection and concatenate the appropriate - validation messages into one message for display to the user. - - We'll use the form and `formError` collection properties in the template. Notice that when using the reactive forms approach, - the amount of code required for each control in the template is signficantly reduced. - -+makeExample('cb-form-validation/ts/app/reactive/hero-form-reactive.component.html','name-with-error-msg','app/reactive/hero-form-reactive.component.html') + Until then, apply the `required` attribute _and_ add the `Validator.required` function + to the control model, as we'll do below. :marked - In the template, define a standard label and set up an input box for validation as follows: - - Set the `formControlName` directive to the name of the control as defined in the `FormBuilder`'s `group` method, `name` in this example. + - the `formControlName` replaces the `name` attribute; it serves the same + purpose of correlating the input box with the Angular form control. - In this example we also used `ngClass` to set a style on required fields. This is optional and based on the styling - you select for your application. + - the two-way `[(ngModel)]` binding is gone. + The reactive approach does not use data binding to move data into and out of the form controls. + We do that in code. - In the `div` element for the validation messages, we use the validation messages collection (`formError` in this example) to determine whether to display a validation message. - - We use `*ngIf` to check whether the control has a validation message in the collection. - - If so, we display it to the user using interpolation. +.l-sub-section + :marked + The retreat from data binding is a principle of the reactive paradigm rather than a technical limitation. +:marked + ### Component class - Repeat for each data entry control on the form. + The component class is now responsible for defining and managing the form control model. + + Angular no longer derives the control model from the template so we can no longer query for it. + We create the Angular form control model explicitly with the help of the `FormBuilder`. - The template then has no validation logic. If there is a validation message in the collection it displays it, if not - it doesn't. All of the logic is in the component class. + Here's the section of code devoted to that process, paired with the template-driven code it replaces: ++makeTabs( + `cb-form-validation/ts/app/reactive/hero-form-reactive.component.ts, + cb-form-validation/ts/app/template/hero-form-template2.component.ts`, + 'form-builder, view-child', + `reactive/hero-form-reactive.component.ts (FormBuilder), + template/hero-form-template2.component.ts (ViewChild)`) +:marked + - we inject the `FormBuilder` in a constructor. - Use this technique when you want better control over the validation rules and messsages. - - Here are the pertinent files for the reactive forms approach: - -+makeTabs( - `cb-form-validation/ts/app/reactive/hero-form-reactive.module.ts, - cb-form-validation/ts/app/reactive/hero-form-reactive.component.html, - cb-form-validation/ts/app/reactive/hero-form-reactive.component.ts, - cb-form-validation/ts/app/shared/hero.ts, - cb-form-validation/ts/app/shared/submitted.component.ts`, - '', - `app/reactive/hero-form-reactive.module.ts, - app/reactive/hero-form-reactive.component.html, - app/reactive/hero-form-reactive.component.ts, - app/shared/hero.ts, - app/shared/submitted.component.ts`) + - we call a `buildForm` method in the `ngOnInit` [lifecycle hook method](../guide/lifecycle-hooks.html#hooks-overview) + because that's when we'll have the hero data. We'll call it again in the `addHero` method. +.l-sub-section + :marked + A real app would retrieve the hero asynchronously from a data service, a task best performed in the `ngOnInit` hook. +:marked + - the `buildForm` method uses the `FormBuilder` (`fb`) to declare the form control model. + Then it attaches the same `onValueChanged` handler to the form. :marked - [Back to top](#top) + #### _FormBuilder_ declaration + The `FormBuilder` declaration object specifies the three controls of the sample's hero form. + + Each control spec is a control name with an array value. + The first array element is the current value of the corresponding hero field. + The (optional) second value is a validator function or an array of validator functions. + + Most of the validator functions are stock validators provided by Angular as static methods of the `Validators` class. + Angular has stock validators that correspond to the standard HTML validation attributes. + + The `forbiddenNames` validator on the `"name"` control is a custom validator, + discussed in a separate [section below](#custom-validation). + +.l-sub-section + :marked + Learn more about `FormBuilder` in a _forthcoming_ chapter on reactive forms. + +:marked + #### Committing hero value changes + + In two-way data binding, the user's changes flow automatically from the controls back to the data model properties. + Reactive forms do not use data binding to update data model properties. + The developer decides _when and how_ to update the data model from control values. + + This sample updates the model twice: + 1. when the user submits the form + 1. when the user chooses to add a new hero + + The `onSubmit` method simply replaces the `hero` object with the combined values of the form: ++makeExample('cb-form-validation/ts/app/reactive/hero-form-reactive.component.ts','on-submit')(format='.') +.l-sub-section + :marked + This example is "lucky" in that the `heroForm.value` properties _just happen_ to + correspond _exactly_ to the hero data object properties. +:marked + The `addHero` method discards pending changes and creates a brand new `hero` model object. ++makeExample('cb-form-validation/ts/app/reactive/hero-form-reactive.component.ts','add-hero')(format='.') +:marked + Then it calls `buildForm` again which replaces the previous `heroForm` control model with a new one. + The `` tag's `[formGroup]` binding refreshes the page with the new control model. + + Finally, it calls the `onValueChanged` handler to clear previous error messages and reset them + to reflect Angular's validation of the new `hero` object. + + Here's the complete reactive component file, compared to the two template-driven component files. ++makeTabs( + `cb-form-validation/ts/app/reactive/hero-form-reactive.component.ts, + cb-form-validation/ts/app/template/hero-form-template2.component.ts, + cb-form-validation/ts/app/template/hero-form-template1.component.ts`, + '', + `reactive/hero-form-reactive.component.ts (#3), + template/hero-form-template2.component.ts (#2), + template/hero-form-template1.component.ts (#1)`) + +.l-sub-section + :marked + Run the [live example](#live-example) to see how the reactive form behaves + and to compare all of the files in this cookbook sample. + +.l-main-section +a#custom-validation +:marked + ## Custom validation + This cookbook sample has a custom `forbiddenNamevalidator` function that's applied to both the + template-driven and the reactive form controls. It's in the `app/shared` folder + and declared in the `SharedModule`. + + Here's the `forbiddenNamevalidator` function itself: ++makeExample('cb-form-validation/ts/app/shared/forbidden-name.directive.ts','custom-validator', 'shared/forbidden-name.directive.ts (forbiddenNameValidator)')(format='.') +:marked + The function is actually a factory that takes a regular expression to detect a _specific_ forbidden name + and returns a validator function. + + In this sample, the forbidden name is "bob"; + the validator rejects any hero name containing "bob". + Elsewhere it could reject "alice" or any name that the configuring regular expression matches. + + The `forbiddenNamevalidator` factory returns the configured validator function. + That function takes an Angular control object and returns _either_ + null if the control value is valid _or_ a validation error object. + The validation error object typically has a property whose name is the validation key ('forbiddenName') + and whose value is an arbitrary dictionary of values that we could insert into an error message (`{name}`). + +.l-sub-section + :marked + Learn more about validator functions in a _forthcoming_ chapter on custom form validation. +:marked + #### Custom validation directive + In the reactive forms component we added a configured `forbiddenNamevalidator` + to the bottom of the `'name'` control's validator function list. ++makeExample('cb-form-validation/ts/app/reactive/hero-form-reactive.component.ts','name-validators', 'reactive/hero-form-reactive.component.ts (name validators)')(format='.') +:marked + In the template-driven component template, we add the selector (`forbiddenName`) of a custom _attribute directive_ to the name's input box + and configured it to reject "bob". ++makeExample('cb-form-validation/ts/app/template/hero-form-template2.component.html','name-input', 'template/hero-form-template2.component.html (name input)')(format='.') +:marked + The corresponding `ForbiddenValidatorDirective` is a wrapper around the `forbiddenNamevalidator`. + + Angular forms recognizes the directive's role in the validation process because the directive registers itself + with the `NG_VALIDATORS` provider, a provider with an extensible collection of validation directives. ++makeExample('cb-form-validation/ts/app/shared/forbidden-name.directive.ts','directive-providers', 'shared/forbidden-name.directive.ts (providers)')(format='.') +:marked + The rest of the directive is unremarkable and we present it here without further comment. ++makeExample('cb-form-validation/ts/app/shared/forbidden-name.directive.ts','directive', 'shared/forbidden-name.directive.ts (directive)') +:marked +.l-sub-section + :marked + See the [Attribute Directives](../guide/attribute-directives.html) chapter. + +.l-main-section +a#testing +:marked + ## Testing Considerations + + We can write _isolated unit tests_ of validation and control logic in _Reactive Forms_. + + _Isolated unit tests_ probe the component class directly, independent of its + interactions with its template, the DOM, other dependencies, or Angular itself. + + Such tests have minimal setup, are quick to write, and easy to maintain. + They do not require the `Angular TestBed` or asynchronous testing practices. + + That's not possible with _Template-driven_ forms. + The template-driven approach relies on Angular to produce the control model and + to derive validation rules from the HTML validation attributes. + You must use the `Angular TestBed` to create component test instances, + write asynchronous tests, and interact with the DOM. + + While not difficult, this takes more time, work and skill — + factors that tend to diminish test code coverage and quality. diff --git a/public/resources/images/cookbooks/form-validation/plunker.png b/public/resources/images/cookbooks/form-validation/plunker.png index 0df5840a525f41345792e99f36555a51a0f20e49..c1fd3eed096b8681e9b619a2de3474c07e76470b 100644 GIT binary patch literal 21082 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 K+T~hyq5lQ%I+4@> literal 25379 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

8gt82N#X9R0W^H5H%pOUD7ESf1hYMw7a< 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 tw