Angular 2.0 forms

Post on 20-Jan-2017

1,533 views 0 download

transcript

AngularJS 2.0 Forms

Eyal Vardi

Site: http://ng-course.org

Blog: eyalVardi.wordpres.com

Agenda Template Driven

Two-way data binding with ngModel Change tracking with ngControl ngForm

Model Driven Control & ControlGroup Form Builder

Validations Value Accessors

Form Directives (Template Driven)

Installation The forms classes exist in

'angular2/common'import { FORM_DIRECTIVES } from 'angular2/common';

ngFormngFormModel

ngModelngControl

ngFormControl

Controls (Model Driven)

Valid

ator

s

Acce

ssor

s

ControlControlGroupControlArray

My Component

(Model)name: string

Form Control’s Classes

ControlControlGroupControlArray

Component View Template

<input type="text" [(ngModel)] ="name" />

pristine dirty touched untouche

d errors valid

Data Flow

Template Driven

ngModel Directive Binds an existing domain model to a

form control.@Component({ selector: "search-comp", directives: [FORM_DIRECTIVES], template: `<input type='text' [(ngModel)]="name">`})class SearchComp { name: string;}

Inside [(ngModel)] 1/2

<input type="text" class="form-control"

required

[ngModel]="model.name"

(ngModelChange)="model.name =

$event" >

Name: {{model.name}}

Property Binding, a value flows from the model to a target property on screen.

Event Binding, we flow the value from the target property on screen to the model.

Inside [(ngModel)] 2/2@Directive({ selector: '[ngModel]:not([ngControl]):not([ngFormControl])', bindings: [formControlBinding], inputs : ['model: ngModel'], outputs : ['update: ngModelChange'], exportAs: 'ngForm'})export class NgModel extends NgControl implements OnChanges { _control = new Control(); /** @internal */ _added = false; /** @internal */ update = new EventEmitter(); model: any; viewModel: any;

constructor(...) {...} /** Properties & Methods */ }

ngControl Directive (NgControlName) Creates and binds a control with a

specified name to a DOM element.

<form #f="ngForm" (submit)='onLogIn(f.value)'>

Login <input type='text' ngControl='login'

#l="ngForm">

<div *ngIf="!l.valid">Login is invalid</div>

</form>

Component Field

Component Template Directive that in use

name : string

<input [(ngModel)]=“name” /> ngModel

name : string

<input ngControl=“dName” [(ngModel)]=“name” />

ngControlName

ngModel vs. ngControlName ngControlName directive selector

'[ngControl]'

ngModel directive selector '[ngModel]:not([ngControl]):not([ngFormControl])

'

This is still a ngControl

ngControl Properties Properties:

formDirective control value path validator asyncValidator

States Properties: pristine dirty touched untouched errors valid

Abstract class

Track change-state and validity

State Class if true Class if false

Control has been visited ng-touched ng-untouched

Control's value has changed ng-dirty ng-pristine

Control's value is valid ng-valid ng-invalid

NgControlStatus Directive Sets CSS classes based on ngControl

directive status (valid/invalid/dirty/etc).@Directive({ selector: '[ngControl],[ngModel],[ngFormControl]', host: { '[class.ng-untouched]': 'ngClassUntouched', '[class.ng-touched]' : 'ngClassTouched', '[class.ng-pristine]' : 'ngClassPristine', '[class.ng-dirty]' : 'ngClassDirty', '[class.ng-valid]' : 'ngClassValid', '[class.ng-invalid]' : 'ngClassInvalid' }})export class NgControlStatus { private _cd: NgControl; constructor(@Self() cd: NgControl) { this._cd = cd; } ...

get ngClassValid(): boolean { return isPresent(this._cd.control) ? this._cd.control.valid : false; } ...}

Data BindingTrack change-state

and validity

Validators

Control

My Component (model)

ngModel Directives ngControlName

ngFormControl

ngModelselector :

'[ngModel]:not([ngControl]):not([ngFormControl])',Inputs : ['model: ngModel'],

outputs : ['update: ngModelChange'],

selector : '[ngFormControl]'inputs : ['form: ngFormControl', 'model: ngModel'],outputs : ['update: ngModelChange'],

selector : '[ngControl]',inputs : ['name: ngControl', 'model: ngModel'],outputs : ['update: ngModelChange'],

Form Tag & NgForm Directive NgForm will get automatically attached to

any <form> tags you have in your view, when we used FORM_DIRECTIVES. A ControlGroup named ngForm A (ngSubmit) output

<form #f="ngForm" (ngSubmit)="onSubmit(f.value)"></form>

ExportAs

Output

Form Directives

Use on input tagUse on form tag

Errors Messages Form message

Field message

Specific validation

<div *ngIf="!myForm.valid" class="ui error message">Form is invalid

</div>

<div *ngIf="!name.valid" class="ui message" [class.error]="!name.valid && name.touched" >

Name is invalid</div>

<div *ngIf="name.hasError('required')" class="ui error message">Name is required</div>

Model Driven

Form Controls `Control`s have values and validation

state

AbstractControl Class Events:

valueChanges statusChanges

Methods: setErrors,getErrors & hasErrors find setParent markAsDirty,markAsXXX runValidator

Properties: value status valid errors pristine dirty touched untouched

Model Driven Forms A Control represents a single input field Controls encapsulate the field's value,

and states such as if it is valid, dirty (changed), or has errors.

Directives Controls

ngFormModel ControlGroup | ControlArray

ngFormControl Control

ngFormModel & ngFormControl ngFormModel Binds an existing control

group to a DOM element. ngFormControl Binds an existing Control

to a DOM element.

export class App { constructor() { this.myForm = new ControlGroup({ myControl: new Control("") }); }}

<form [ngFormModel]="myForm"> <input ngFormControl="myControl"></form>

FormBuilder Class Creates a form object from a user-

specified configuration. control(value: Object, validator?: Function, asyncValidator?: Function) :

Control group(controls: {[key: string]: any}, extra?: {[key: string]: any}) :

ControlGroup array(controls: any[], validator?: Function, asyncValidator?: Function) :

ControlArrayconstructor(builder: FormBuilder) {

this.loginForm = builder.group({

login: ["", Validators.required],

passwordRetry: builder.group({

password: ["", Validators.required],

pConfirmation: ["", Validators.required]

})

});

}

FormBuilder Class Creates a form object from a user-

specified configuration.@Component({ selector: 'my-app', viewBindings: [FORM_BINDINGS], template: ` <form [ngFormModel]="loginForm"> <p>Login <input ngFormControl="login"></p> <div ngControlGroup="passwordRetry"> <p>Password <input type="password" ngFormControl="password"></p> <p>Confirm password <input type="password" ngFormControl="pConfirma"></p> </div> </form> <h3>Form value:</h3> <pre>{{value}}</pre> `, directives: [FORM_DIRECTIVES]})

export class App { loginForm: ControlGroup; constructor(builder: FormBuilder) { this.loginForm = builder.group({ login: ["", Validators.required], passwordRetry: builder.group({ password: ["", Validators.required], pConfirm: ["", Validators.required] }) }); } get value(): string { return JSON.stringify( this.loginForm.value, null, 2); }}

Watching For Changes Both ControlGroup and Control have an

EventEmitter that we can use to observe changes.this.name.valueChanges.subscribe( (value: string) => { console.log('name changed to: ', value); });

this.myForm.valueChanges.subscribe( (value: string) => { console.log('form changed to: ', value); });

Validations

Built-in Validators Required MaxLength & MinLength

Custom Validator Directive@Directive({ selector: ' [my-validator][ngControl],

[my-validator][ngFormControl], [my-validator][ngModel]', providers: [provide( NG_VALIDATORS, { useExisting: myValidator, multi: true})]})export class myValidator implements Validator { private _validator: Function;

constructor(@Attribute("my-validator") myValidator: string) { this._validator = function(value){ return { "myValidator": true }; } }

validate(c: Control): {[key: string]: any} { return this._validator(c); }}

Returns a StringMap<string, boolean> where the key is "error code" and the value is true if it fails

Custom Validator Assigning the Validator to the Control:

this.myForm = fb.group({ 'name': [

'', Validators.compose([

Validators.required , nameValidator

])]

});

and operation

Value Accessors

Interface ControlValueAccessor A bridge between a control and a native

element. A ControlValueAccessor abstracts the

operations of writing a new value to a DOM element representing an input control.

DefaultValueAccessor Directive The default accessor for writing a value and

listening to changes that is used by the: NgModel NgFormControl NgControlName

InputInput ModelDefaultValueAccessor Renderer On Change

ngModel | ngFormControl | ngControlName

DVA Code@Directive({ selector: 'input:not([type=checkbox])[ngControl],

textarea[ngControl],input:not([type=checkbox])[ngFormControl],textarea[ngFormControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]',

host: { '(input)': 'onChange($event.target.value)', '(blur)' : 'onTouched()'},

bindings: [DEFAULT_VALUE_ACCESSOR]}) export class DefaultValueAccessor implements ControlValueAccessor { onChange = (_) => {}; onTouched = () => {};

constructor(private _renderer:Renderer, private _elementRef:ElementRef) {}

writeValue(value: any): void { var normalizedValue = isBlank(value) ? '' : value; this._renderer.setElementProperty(

this._elementRef, 'value', normalizedValue); } registerOnChange(fn: (_: any) => void): void { this.onChange = fn; } registerOnTouched(fn: () => void): void { this.onTouched = fn; }}

setUpControl function This function are call when the

ngOnChanges in ngModel directive is call in the first time.

export function setUpControl( control: Control , dir: NgControl ): void {

...

dir.valueAccessor.writeValue(control.value);

// view -> model dir.valueAccessor.registerOnChange(newValue => { dir.viewToModelUpdate(newValue); control.updateValue(newValue, {emitModelToViewChange: false}); control.markAsDirty(); });

// model -> view control.registerOnChange(newValue => dir.valueAccessor.writeValue(newValue));

// touched dir.valueAccessor.registerOnTouched(() => control.markAsTouched());}

Form Classes

Resources Angular.io site (Developer guides - forms) Ng-Book 2 (

The Ultimate Guide to Forms in Angular 2 ) GitHub (Angular code source)

Thankseyalvardi.wordpress.com

Eyal Vardi

Site: http://ng-course.org

Blog: eyalVardi.wordpres.com