Angular Reactive Forms – 7

Masih melanjutkan dari modul sebelumnya, pada modul ini akan dibahas membuat custom validator.

Validator pada dasarnya adalah javascript fungsi, yang akan dipanggil Angular untuk melakukan validasi.

Skenarionya adalah kita ingin memastikan username tertentu tidak digunakan.

Buka file app.component.ts, kita akan tambahkan

  • property untuk menyimpan data username yang tidak boleh digunakan.
  • method validator
  • gunakan custom validator pada object form control username.
import { Component, OnInit } from '@angular/core';
import { FormArray, FormControl, FormGroup, Validators } from '@angular/forms';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  genders = ['male', 'female'];
  myForm! : FormGroup;
  // property yang digunakan oleh custom validator.
  forbiddenUsrNm = ['root', 'admin'];

  ngOnInit(){
    this.myForm = new FormGroup({
      'userData' : new FormGroup({
        'username' : new FormControl(null, [Validators.required, this.isForbidNames.bind(this)]),
        'email' : new FormControl(null, [Validators.required, Validators.email]),  
      }),
      'gender' : new FormControl('male'),
      'hobbies' : new FormArray([])
    });
  }

  onSubmit(){
    console.log(this.myForm);
  }

  get usrnm() { return this.myForm.get('userData.username'); }
  get email() { return this.myForm.get('userData.email'); }

  onAddHobby(){
    const ctrl = new FormControl(null, Validators.required);
    (<FormArray>this.myForm.get('hobbies')).push(ctrl);
  }

  get hobbies() {return (this.myForm.get('hobbies') as FormArray).controls;}

  //custom validator
  isForbidNames(ctrl : FormControl): {[s: string]: boolean} {
    // pastikan return bukan -1, karena jika username tidak ditemukan, akan dikembalikan -1, (karena selain 0, adalah true ).
    if (this.forbiddenUsrNm.indexOf(ctrl.value) !==-1){
      return {'nameisforbidden': true}
    }else{
      return null;
    }
  }

}

Sesuai ekspektasi, jika user diisi dengan root atau admin, akan terjadi error validasi.

Kita juga dapat gunakan return error nameisforbidden untuk menampilkan error message yang lebih spesifik.

Buka file app.component.html, modifikasi element error message pada username, dengan memisahkan kedalam 2 span untuk menampilkan message yang sesuai dengan error.

<p *ngIf="usrnm.invalid  && usrnm.touched">
    <span *ngIf="usrnm.errors['nameisforbidden']">Username is forbidden! </span>
    <span *ngIf="usrnm.errors['requiered']">Username is requiered! </span>                 
  </p>

Berikut isi lengkap file app.component.html

<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 [formGroup]="myForm" (ngSubmit)="onSubmit()">
        <div formGroupName="userData">
          <div class="form-group">
            <label for="username">Username</label>
            <input
              type="text"
              id="username"
              class="form-control"
              formControlName="username">
              <!-- custom error message berdasarkan error -->
              <p *ngIf="usrnm.invalid  && usrnm.touched">
                <span *ngIf="usrnm.errors['nameisforbidden']">Username is forbidden! </span>
                <span *ngIf="usrnm.errors['required']">Username is requiered! </span>                 
              </p>
          </div>
          <div class="form-group">
            <label for="email">email</label>
            <input
              type="text"
              id="email"
              class="form-control"
              formControlName="email">
              <p *ngIf="email.invalid  && email.touched">Please input valid email</p>
          </div>
        </div>
        <div class="radio" *ngFor="let gender of genders">
          <label>
            <input
              type="radio"
              [value]="gender"
              formControlName="gender">{{ gender }}
          </label>
        </div>
        <!-- - tambahkan directive formArray, 
        - button untuk menambahkan hobby 
        - looping untuk menambahkan input -->
        <div formArrayName="hobbies">
          <h4>Add Hobbies</h4>
          <button class="btn btn-dark" type="button" (click)="onAddHobby()">Add Hobby</button>
          <div class="form-group"
           *ngFor="let hobby of hobbies; let i = index;">
            <input type="text" class="form-control" [formControlName]="i">
          </div>
        </div>
        <hr>
        <button class="btn btn-primary" type="submit">Submit</button>
      </form>
    </div>
  </div>
</div>
Sharing is caring:

Leave a Comment