Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Form of Art - Angular 2 forms

Form of Art - Angular 2 forms

Forms are a key ingredient in most, if not all, Web applications. In this session we’ll learn how to construct forms with Angular 2, applying code and UX best practices.
Presented at https://js-il.com/ and http://www.meetup.com/AngularJS-IL/events/231885788/

Shmuela Jacobs

June 20, 2016
Tweet

More Decks by Shmuela Jacobs

Other Decks in Technology

Transcript

  1. Angular 2 Forms new version with new API template-driven model-driven

    (reactive) (thanks Kara Erickson!) API changes: https://docs.google.com/document/u/1/d/1RIezQqE4aEhBRmArIAS1mRIZtWFf6JxN_7B4meyWK0Y/pub
  2. using the new forms module npm i @angular/forms bootstrap(AppComponent, [


    disableDeprecatedForms(),
 provideForms() ]); const barrels: string[] = [
 // Angular specific barrels.
 '@angular/core',
 '@angular/common',
 '@angular/forms', Angular CLI: system-config.js
  3. component class import { Component } from '@angular/core';
 
 @Component({


    moduleId: module.id,
 selector: 'sj-demo-template-form',
 templateUrl: 'demo-template-form.component.html',
 styleUrls: ['demo-template-form.component.css']
 })
 export class DemoTemplateFormComponent {
 
 model = {
 userEmail: '[email protected]'
 };
 
 submitForm(formController) {
 this.model = formController.value;
 }
 
 emailHasError(emailControl) {
 return emailControl && emailControl.touched && !emailControl.valid;
 }
 }
  4. <form #userForm="ngForm"
 (ngSubmit)="submitForm(userForm)"
 novalidate
 autocomplete="off"
 class="form-section"> 
 <div class="form-group form-inline">


    <label for="user-email">email: </label> 
 <input id="user-email"
 [ngModel]="model.userEmail"
 name="userEmail"
 required
 minlength="3"
 pattern=".+@.+"
 class="form-control">
 <span *ngIf="emailHasError(userForm.controls.userEmail)"
 class="text-danger">email is not valid</span>
 </div> 
 <button type="submit"
 [disabled]="!userForm.valid"
 class="btn btn-success">Submit</button>
 </form> component template
  5. ngForm <form #userForm="ngForm"
 (ngSubmit)="submitForm(userForm)"> 
 <input [ngModel]="model.userEmail"
 name="userEmail"
 required
 minlength="3"


    pattern=".+@.+"> 
 <span *ngIf="emailHasError(userForm.controls.userEmail)"
 class="text-danger">email is not valid</span>
 
 <button type="submit"
 [disabled]="!userForm.valid">Submit</button>
 </form>
  6. using ngForm <form #userForm="ngForm"
 (ngSubmit)="submitForm(userForm)"> 
 <input [ngModel]="model.userEmail"
 name="userEmail"
 required


    minlength="3"
 pattern=".+@.+"> 
 <span *ngIf="emailHasError(userForm.controls.userEmail)"
 class="text-danger">email is not valid</span>
 
 <button type="submit"
 [disabled]="!userForm.valid">Submit</button>
 </form> submitForm(formController) {
 this.model = formController.value;
 }
  7. ngModel <form #userForm="ngForm"
 (ngSubmit)="submitForm(userForm)"> 
 <input [ngModel]="model.userEmail"
 name="userEmail"
 required
 minlength="3"


    pattern=".+@.+"> 
 <span *ngIf="emailHasError(userForm.controls.userEmail)"
 class="text-danger">email is not valid</span>
 
 <button type="submit"
 [disabled]="!userForm.valid">Submit</button>
 </form> model = {
 userEmail: '[email protected]'
 };
  8. validation <form #userForm="ngForm"
 (ngSubmit)="submitForm(userForm)"> 
 <input [ngModel]="model.userEmail"
 name="userEmail"
 required
 minlength="3"


    pattern=".+@.+"> 
 <span *ngIf="emailHasError(userForm.controls.userEmail)"
 class="text-danger">email is not valid</span>
 
 <button type="submit"
 [disabled]="!userForm.valid">Submit</button>
 </form> emailHasError(emailControl) {
 return emailControl && emailControl.touched && !emailControl.valid;
 }
  9. error message <form #userForm="ngForm"
 (ngSubmit)="submitForm(userForm)"> 
 <input [ngModel]="model.userEmail"
 name="userEmail"
 required


    minlength="3"
 pattern=".+@.+"> 
 <span *ngIf="emailHasError(userForm.controls.userEmail)"
 class="text-danger">email is not valid</span>
 
 <button type="submit"
 [disabled]="!userForm.valid">Submit</button>
 </form> emailHasError(emailControl) {
 return emailControl && emailControl.touched && !emailControl.valid;
 }
  10. form css classes <form #userForm="ngForm"
 (ngSubmit)="submitForm(userForm)"> 
 <input [ngModel]="model.userEmail"
 name="userEmail"


    required
 minlength="3"
 pattern=".+@.+"> 
 <span *ngIf="emailHasError(userForm.controls.userEmail)"
 class="text-danger">email is not valid</span>
 
 <button type="submit"
 [disabled]="!userForm.valid">Submit</button>
 </form> input.ng-invalid.ng-touched {
 border-color: red;
 }
  11. NgForm <form #userForm="ngForm"
 (ngSubmit)="submitForm(userForm)"> 
 <input [ngModel]="model.userEmail"
 name="userEmail"
 required
 minlength="3"


    pattern=".+@.+"> 
 <span *ngIf="emailHasError(userForm.controls.userEmail)"
 class="text-danger">email is not valid</span>
 
 <button type="submit"
 [disabled]="!userForm.valid">Submit</button>
 </form> NgForm dirty pristine touched untouched submitted valid
  12. NgForm <form #userForm="ngForm"
 (ngSubmit)="submitForm(userForm)"> 
 <input [ngModel]="model.userEmail"
 name="userEmail"
 required
 minlength="3"


    pattern=".+@.+"> 
 <span *ngIf="emailHasError(userForm.controls.userEmail)"
 class="text-danger">email is not valid</span>
 
 <button type="submit"
 [disabled]="!userForm.valid">Submit</button>
 </form> NgForm value: { userEmail: ... }
  13. FormGroup <form #userForm="ngForm"
 (ngSubmit)="submitForm(userForm)"> 
 <input [ngModel]="model.userEmail"
 name="userEmail"
 required
 minlength="3"


    pattern=".+@.+"> 
 <span *ngIf="emailHasError(userForm.controls.userEmail)"
 class="text-danger">email is not valid</span>
 
 <button type="submit"
 [disabled]="!userForm.valid">Submit</button>
 </form> NgForm form control FormGroup pending: boolean status: 'VALID' / 'INVALID' / 'PENDING'
  14. FormControl <form #userForm="ngForm"
 (ngSubmit)="submitForm(userForm)"> 
 <input [ngModel]="model.userEmail"
 name="userEmail"
 required
 minlength="3"


    pattern=".+@.+"> 
 <span *ngIf="emailHasError(userForm.controls.userEmail)"
 class="text-danger">email is not valid</span>
 
 <button type="submit"
 [disabled]="!userForm.valid">Submit</button>
 </form> NgForm controls: { userEmail } FormControl value: '[email protected]' status pending valid touched untouched dirty pristine
  15. <form #userForm="ngForm"
 (ngSubmit)="submitForm(userForm)"> 
 <input [ngModel]="model.userEmail"
 name="userEmail"
 required
 minlength="3"
 pattern=".+@.+">

    
 <span *ngIf="emailHasError(userForm.controls.userEmail)"
 class="text-danger">email is not valid</span>
 
 <button type="submit"
 [disabled]="!userForm.valid">Submit</button>
 </form> FormControl NgForm controls: { userEmail } FormControl errors: { pattern: { actualValue: 's' requiredPattern: '^.+@.+$' }, minlength: actualLength: 2 requiredLength: 3 } }
  16. Form Groups <form #userForm="ngForm"
 (ngSubmit)="submitForm(userForm)"> 
 <input [ngModel]="model.userEmail"
 name="userEmail"
 required


    minlength="3"
 pattern=".+@.+"> 
 <span *ngIf="emailHasError(userForm.controls.userEmail)"
 class="text-danger">email is not valid</span>
 
 <button type="submit"
 [disabled]="!userForm.valid">Submit</button>
 </form>
  17. Form Groups <form #userForm="ngForm"
 (ngSubmit)="submitForm(userForm)"> <div ngModelGroup="userDetails" #userDetailsGroup="ngModelGroup"> 
 <input

    [ngModel]="model.userDetails.userEmail"
 name="userName"
 required
 pattern="[A-Za-z]{2,}"> <input [ngModel]="model.userDetails.userEmail"
 name="userEmail"
 required
 minlength="3"
 pattern=".+@.+">
 </div> <div *ngIf="userDetailsGroup.dirty && !userDetailsGroup.valid">details are not valid</div> 
 <button type="submit" [disabled]="!userForm.valid">Submit</button>
 </form>
  18. Form Groups <form #userForm="ngForm"
 (ngSubmit)="submitForm(userForm)"> <div ngModelGroup="userDetails" #userDetailsGroup="ngModelGroup"> 
 <input

    [ngModel]="model.userDetails.userEmail"
 name="userName"
 required
 pattern="[A-Za-z]{2,}"> <input [ngModel]="model.userDetails.userEmail"
 name="userEmail"
 required
 minlength="3"
 pattern=".+@.+">
 </div> <div *ngIf="userDetailsGroup.dirty && !userDetailsGroup.valid">details are not valid</div> 
 <button type="submit" [disabled]="!userForm.valid">Submit</button>
 </form> NgForm value: { userDetails: { userName: '', userEmail: '' } }, controls: { userDetails } FormGroup controls: { userName, userEmail } FormControl
  19. NgModelGroup <form #userForm="ngForm"
 (ngSubmit)="submitForm(userForm)"> <div ngModelGroup="userDetails" #userDetailsGroup="ngModelGroup"> 
 <input [ngModel]="model.userDetails.userEmail"


    name="userName"
 required
 pattern="[A-Za-z]{2,}"> <input [ngModel]="model.userDetails.userEmail"
 name="userEmail"
 required
 minlength="3"
 pattern=".+@.+">
 </div> <div *ngIf="userDetailsGroup.dirty && !userDetailsGroup.valid">details are not valid</div> 
 <button type="submit" [disabled]="!userForm.valid">Submit</button>
 </form> NgModelGroup value: { userName: '', userEmail: '' }, name: 'userDetails' control FormGroup controls: { userName, userEmail } FormControl
  20. model-driven (reactive) form import { Component } from '@angular/core'; import

    { REACTIVE_FORM_DIRECTIVES, FormGroup, FormControl } from '@angular/forms'; 
 @Component({ ... ,
 directives: [REACTIVE_FORM_DIRECTIVES] })
 export class DemoTemplateFormComponent {
 
 userNameControl = new FormControl(); userEmailControl = new FormControl(); userDetailsGroup = new FormGroup({
 userName: this.userNameControl, userEmail: this.userEmailControl
 }); 
 userForm = new FormGroup({
 userDetails: this.userDetailsGroup
 }); 
 submitForm() { ... } }
  21. model-driven (reactive) form import { Component } from '@angular/core'; import

    { REACTIVE_FORM_DIRECTIVES, FormGroup, FormControl } from '@angular/forms'; 
 @Component({ ... ,
 directives: [REACTIVE_FORM_DIRECTIVES] })
 export class DemoTemplateFormComponent {
 
 userNameControl = new FormControl(); userEmailControl = new FormControl(); userDetailsGroup = new FormGroup({
 userName: this.userNameControl, userEmail: this.userEmailControl
 }); 
 userForm = new FormGroup({
 userDetails: this.userDetailsGroup
 }); 
 submitForm() { ... } }
  22. model-driven (reactive) form <form [formGroup]="userForm"
 (ngSubmit)="submitForm()">
 
 <div formGroupName="userDetails">
 <input

    formControlName="userName">
 <input formControlName="userEmail"> 
 </div>
 
 <div *ngIf="userDetailsGroup.dirty && !userDetailsGroup.valid"> email is not valid
 </div>
 
 <button type="submit"
 [disabled]="!userForm.valid">Submit
 </button>
 
 </form>
  23. model-driven (reactive) form userNameControl = new FormControl(); userEmailControl = new

    FormControl(); userDetailsGroup = new FormGroup({
 userName: this.userNameControl, userEmail: this.userEmailControl
 }); userForm = new FormGroup({
 userDetails: this.userDetailsGroup
 }); <form [formGroup]="userForm"
 (ngSubmit)="submitForm()">
 
 <div formGroupName="userDetails">
 <input formControlName="userName">
 <input formControlName="userEmail"> 
 </div>
 </form>
  24. model-driven (reactive) form userNameControl = new FormControl(); userEmailControl = new

    FormControl(); userDetailsGroup = new FormGroup({
 userName: this.userNameControl, userEmail: this.userEmailControl
 }); userForm = new FormGroup({
 userDetails: this.userDetailsGroup
 }); <form [formGroup]="userForm"
 (ngSubmit)="submitForm()">
 
 <div formGroupName="userDetails">
 <input formControlName="userName">
 <input formControlName="userEmail"> 
 </div>
 </form>
  25. initial value import { Component } from '@angular/core'; import {

    REACTIVE_FORM_DIRECTIVES, FormGroup, FormControl } from '@angular/forms'; 
 @Component({ ... ,
 directives: [REACTIVE_FORM_DIRECTIVES] })
 export class DemoTemplateFormComponent {
 
 userNameControl = new FormControl(); userEmailControl = new FormControl( '[email protected]' ); userDetailsGroup = new FormGroup({
 userName: this.userNameControl, userEmail: this.userEmailControl
 }); 
 userForm = new FormGroup({
 userDetails: this.userDetailsGroup
 });
  26. validation import { Component } from '@angular/core'; import { REACTIVE_FORM_DIRECTIVES,

    FormGroup, FormControl } from '@angular/forms'; 
 @Component({ ... ,
 directives: [REACTIVE_FORM_DIRECTIVES] })
 export class DemoTemplateFormComponent {
 
 userNameControl = new FormControl(); userEmailControl = new FormControl( '[email protected]', Validators.required ); userDetailsGroup = new FormGroup({
 userName: this.userNameControl, userEmail: this.userEmailControl
 }); 
 userForm = new FormGroup({
 userDetails: this.userDetailsGroup
 });
  27. validation import { Component } from '@angular/core'; import { REACTIVE_FORM_DIRECTIVES,

    FormGroup, FormControl } from '@angular/forms'; 
 @Component({ ... ,
 directives: [REACTIVE_FORM_DIRECTIVES] })
 export class DemoTemplateFormComponent {
 
 userNameControl = new FormControl(); userEmailControl = new FormControl( '[email protected]', [Validators.required, Validators.pattern('.+@.+')] ); userDetailsGroup = new FormGroup({
 userName: this.userNameControl, userEmail: this.userEmailControl
 }); 
 userForm = new FormGroup({
 userDetails: this.userDetailsGroup
 });