Implementasi Reactive Form – 4

Pada modul ini kita akan mengimplementasikan validasi pada form. Sengaja kami pisahkan agar tutorial menjadi lebih mudah dipahami.

Buka file recipe-edit.component.ts, kita akan gunakan validator built-in dari Angular. (lihat code dengan bagian comment)

import { Component, OnInit } from '@angular/core';
//tambahkan library validators jika tidak ditambahkan otomatis oleh IDE.
import { FormArray, FormControl, FormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, Params } from '@angular/router';
import { RecipeService } from '../recipe.service';

@Component({
  selector: 'app-recipe-edit',
  templateUrl: './recipe-edit.component.html',
  styleUrls: ['./recipe-edit.component.css']
})
export class RecipeEditComponent implements OnInit {
  id! : number;
  editMode = false;
  recipeForm! : FormGroup;

  constructor(private route: ActivatedRoute, private recipeSrv : RecipeService) { }

  ngOnInit(): void {
    this.route.params.subscribe(
      (params : Params) =>{
        this.id = +params['id'];
        this.editMode = params['id'] != null;
        this.initForm();
      }
    );
  }

  private initForm(){
    let recipeNm = '';
    let recipeImg = '';
    let recipeDesc = '';
    let recipeIngredients = new FormArray([]);

    if (this.editMode){
      const recipe = this.recipeSrv.getRecipe(this.id);
      recipeNm = recipe.name;
      recipeImg = recipe.imgPath;
      recipeDesc = recipe.description;
      if (recipe['ingredients']){
        for (let ing of recipe.ingredients){
          recipeIngredients.push(
            new FormGroup({
              //tambahkan validator pada argument kedua dari FormControl
              'name' : new FormControl(ing.name, Validators.required),
              'amount' : new FormControl(ing.amount, [Validators.required, Validators.pattern(/^[1-9]+[0-9]*$/)])
            })
          );
        }
      }
    }
    this.recipeForm = new FormGroup({
      //menambahkan validator pada argument kedua dari FormControl.
      'name': new FormControl(recipeNm, Validators.required),
      'imgPath': new FormControl(recipeImg, Validators.required),
      'description': new FormControl(recipeDesc, Validators.required),
      'ingredients': recipeIngredients
    });
  }

  
  onAddIngredient(){
    (<FormArray>this.recipeForm.get('ingredients')).push(
      new FormGroup({
        'name': new FormControl(),
        'amount' : new FormControl()
      })
    );
  }

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

  get ingredientsCtrl(){
    return (<FormArray>this.recipeForm.get('ingredients')).controls;
  }

}

Berikutnya kita buka recipe-edit.component.html, lalu implementasikan validasi yang sudah tersedia.

<div class="row">
    <div class="col-xs-12">
        <form [formGroup]="recipeForm" (ngSubmit)="onSubmit()">
            <div class="row">
                <div class="col-12">
                    <!-- disabled button jika validasi gagal -->
                    <button type="submit" class="btn btn-success" [disabled]="recipeForm.invalid">Save</button>
                    <button type="submit" class="btn btn-danger">Cancel</button>
                </div>
            </div>
            <div class="row">
                <div class="col-12">
                    <div class="form-group">
                        <label for="name">Name</label>
                        <input type="text" class="form-control" id="name" formControlName="name">
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="col-12">
                    <div class="form-group">
                        <label for="imgPath">Image URL</label>
                        <input type="text" class="form-control" id="imgPath" formControlName="imgPath">
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="col-12">
                    <img src="" class="img-fluid.">
                </div>
            </div>            
            <div class="row">
                <div class="col-12">
                    <div class="form-group">
                        <label for="description">Description</label>
                        <textarea class="form-control" id="description" rows="5" formControlName="decription"></textarea>
                    </div>
                </div>
            </div>
            <div class="row mt-2">
                <div class="col-12" formArrayName="ingredients">
                    <div class="row" 
                    *ngFor="let ingCtrl of ingredientsCtrl; let i = index"
                    [formGroupName]="i">
                        <div class="col-8">
                            <input type="text" class="form-control" formControlName="name">
                        </div>
                        <div class="col-2">
                            <input type="number" class="form-control" formControlName="amount">
                        </div>
                        <div class="col-2">
                            <button class="btn btn-danger">X</button>
                        </div>                        
                    </div>
                    <hr>
                    <div class="row">
                        <div class="col-12">
                            <button type="button" class="btn btn-success" (click)="onAddIngredient()">Add</button>
                        </div>
                    </div>
                </div>
            </div>
        </form>
    </div>
</div>

Kemudian buka file recipe-edit.component.css, untuk menambahkan css rule untuk element form yang invalid.

Perhatian: class ng-touched, memastikan element html yang sudah dikunjungi yang akan divalidasi. Untuk mencegah css rule diterapkan pada form baru tampil.

input.ng-invalid.ng-touched, 
textarea.ng-invalid.ng-touched {
    border: 1px solid red;
}

Sesuai ekspektasi, validasi sudah berfungsi dengan baik.

Pada modul selanjutnya kita akan mengimplementasikan form submit.

Sharing is caring:

Leave a Comment