# Forms Angular offers two different approach to retrieving data from a from. - Template-driven (predefined) - Reactive (Manual setup but flexible) ## Template driven ### Creating the Form and registering the controls Import the Form module in the `app.module.ts`. ```ts import { FormsModule } from '@angular/forms'; @NgModules({ imports: [ FormsModule ] }) ``` Register the imput with the `ngModel` directive. overview ### Submitting and using the Form app.component.html ```html
``` app.component.ts ```ts onSubmit(form: ngForm) { console.log(form); } ``` overview #### @ViewChild Here we can retrive the data also without submitting the form ```ts import { ViewChild } from '@angular/core'; export class AppComponent { @ViewChild('f') signupForm: ngForm; onSubmit() { console.log(this.signupForm); } ``` ### FormValidation By adding an attribute like `required`, `email` to the html form. Angular detects as a directive and validates it automatically. [Angular Validators](https://angular.io/api/forms/Validators) #### Using the Form state ```html ``` The `f` referes to the local reference declaredy§ in the form. Visually can be showen that a input is invalid by adding this CSS definition. ```css input.ng-invalid.ng-touched { border: 1px solid red; } ``` It shows only a red boder when the input field has been modified. Showing some hint text ```html Please enter a valid email! ``` `setValue` and `patchValue` helps to preset the form with predefined values. With `setValue` overrides the whole form, and `patchValue` updates only a specific inputfield. `patchValue` is aviable only from the `form` (`signupForm.form.patchValue({userData: { username: 'bliblubla'}});`). ## Reactive driven Import the Form module in the `app.module.ts`. ```ts import { ReactiveFormsModule } from '@angular/forms'; @NgModules({ imports: [ ReactiveFormsModule ] }) ``` app.component.html ```html
This name is invalid! This field is required!
Please enter a valid email!

Your Hobbies

Please enter valid data!
``` app.component.ts ```ts import { Component, OnInit } from '@angular/core'; import { FormArray, FormControl, FormGroup, Validators } from '@angular/forms'; import { Observable } from 'rxjs/Observable'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { genders = ['male', 'female']; signupForm: FormGroup; forbiddenUsernames = ['Chris', 'Anna']; constructor() {} ngOnInit() { this.signupForm = new FormGroup({ 'userData': new FormGroup({ 'username': new FormControl(null, [Validators.required, this.forbiddenNames.bind(this)]), 'email': new FormControl(null, [Validators.required, Validators.email], this.forbiddenEmails) }), 'gender': new FormControl('male'), 'hobbies': new FormArray([]) }); // this.signupForm.valueChanges.subscribe( // (value) => console.log(value) // ); this.signupForm.statusChanges.subscribe( (status) => console.log(status) ); this.signupForm.setValue({ 'userData': { 'username': 'Max', 'email': 'max@test.com' }, 'gender': 'male', 'hobbies': [] }); this.signupForm.patchValue({ 'userData': { 'username': 'Anna', } }); } onSubmit() { console.log(this.signupForm); this.signupForm.reset(); } onAddHobby() { const control = new FormControl(null, Validators.required); (this.signupForm.get('hobbies')).push(control); } forbiddenNames(control: FormControl): {[s: string]: boolean} { if (this.forbiddenUsernames.indexOf(control.value) !== -1) { return {'nameIsForbidden': true}; } return null; } forbiddenEmails(control: FormControl): Promise | Observable { const promise = new Promise((resolve, reject) => { setTimeout(() => { if (control.value === 'test@test.com') { resolve({'emailIsForbidden': true}); } else { resolve(null); } }, 1500); }); return promise; } } ```