nezhar
3/18/2018 - 9:01 PM

Template Driven Forms

Forms are using a kind of ElementRef that gets a value assigned, which will be the NgForm.

ViewChild is usefull as it can be used to access the form in an earlier stage of the component life cycle.

Validator can be added as directives in the template: required, email https://angular.io/api/forms/Validators https://angular.io/api?query=validator&type=directive

Angular Adds clases for the validation state on each ngModel field.

ngModel supports:

  • no binding: to inform the form if the field
  • property binding: to set defaults
  • two way binding: can be used directly in the template or for some other purpose
<div class="container">
  <div class="row">
    <div class="col-xs-12 col-sm-10 col-md-8 col-sm-offset-1 col-md-offset-2">
      <form (ngSubmit)="onSubmit()" #f="ngForm">

        <!-- Grouping data is posible in the form, maybe a good idea for nested serializers -->
        <div id="user-data" ngModelGroup="userData" #userData="ngModelGroup">
          <div class="form-group">
            <label for="username">Username</label>
            <input type="text" id="username" class="form-control" ngModel name="username" required>
          </div>
          <button class="btn btn-default" type="button" (click)="suggestUserName()">Suggest an Username</button>
          <div class="form-group">
            <label for="email">Mail</label>
            <input type="email" id="email" class="form-control" ngModel name="email" required email #email="ngModel">
            <span class="help-block" *ngIf='!email.valid && email.touched'>Please enter a valid email!</span>
          </div>
        </div>
        <p *ngIf="!userData.valid && userData.touched">Group invalid</p>

        <div class="form-group">
          <label for="secret">Secret Questions</label>
          <select id="secret" class="form-control" [ngModel]="'pet'" name="secret">
            <option value="pet">Your first Pet?</option>
            <option value="teacher">Your first teacher?</option>
          </select>
        </div>
        <div class="form-group">
          <textarea name="questionAnswer" rows="3" [(ngModel)]="answer"></textarea>
        </div>
        <p>Your reply: {{ answer }}</p>

        <div class="radio" *ngFor="let gender of genders">
            <label>
              <input type="radio" name="gender" ngModel [value]="gender">
              {{ gender }}
            </label>
        </div>

        <button class="btn btn-primary" type="submit" [disabled]="!f.valid">Submit</button>
      </form>
    </div>
  </div>
</div>
.container {
  margin-top: 30px;
}

form .ng-invalid.ng-touched {
  border: 1px solid red;
}
import { Component } from '@angular/core';
import { NgForm } from '@angular/forms';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  suggestUserName() {
    const suggestedName = 'Superuser';
  }

  onSubmit(form: NgForm) {
    console.log("Submited!");
    console.log(form); // #f="ngForm" , onSubmit(f)
    console.log(form.value);
  }
}
import { Component, ViewChild } from '@angular/core';
import { NgForm } from '@angular/forms';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  @ViewChild('f') form: NgForm;

  answer = '';
  genders = ['male', 'female'];

  suggestUserName() {
    const suggestedName = 'Superuser';

/*     this.form.setValue({
      userData: {
        username: suggestedName,
        email: '',
      },
      secret: 'pet',
      questionAnswer: '',
      gender: 'male',
    }); */

    this.form.form.patchValue({
      userData: {
        username: suggestedName
      }
    });
  }

  onSubmit() {
    console.log('Submited!');
    console.log(this.form); // #f="ngForm"
    console.log(this.form.value);

    // Reset form
    this.form.reset();
  }

}