【Angular】実装メモ~Form編~

Form

  • FormGroupで実装

  • 入力フォームを次の仕様で作る

    • 縦並び

    • バリデーション付き

    • バリデーションエラー時はボタンを非活性

    • UIライブラリにAngular Material + flex-layoutを使用

 

 

実装イメージ

(初期表示)

f:id:kanmi-program:20201130191051p:plain

 

(入力時)

f:id:kanmi-program:20201130191109p:plain

 

(エラー時)

f:id:kanmi-program:20201130191125p:plain

 

 

実装

  • app.module

// インポートを追加
import { MatInputModule } from '@angular/material/input';
import { MatButtonModule } from '@angular/material/button';
import { FlexLayoutModule } from '@angular/flex-layout';

// NgModuleに追加
imports: [
   // Angular Materialのモジュールを追加
   MatInputModule,
   MatButtonModule,
   // flex-layoutのモジュールを追加
   FlexLayoutModule,
]

 

  • component

import { Router } from '@angular/router';
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Store } from '@ngrx/store';
import { UserActions } from 'src/app/state/action/user-actions';
import { AppStore } from 'src/app/state/store/store-definition';

import { integerValidator } from "src/app/validator/sample-validator";

@Component({
 selector: 'app-test',
 templateUrl: './test.component.html',
 styleUrls: ['./test.component.scss'],
})
export class TestComponent implements OnInit {
 constructor(
   private fb: FormBuilder,
   private router: Router,
   private store: Store<AppStore>
) {}

 public sampleForm: FormGroup;
 ngOnInit() {
   this.initForm();
}

 // フォームの初期化処理
 initForm() {
   this.sampleForm = this.fb.group({
     // バリデーターの設定
     // 第一引数に初期値、第二引数にバリデーター
     userId: ['', [Validators.required, integerValidator()]],
     password: ['', Validators.required],
  });
}

 login(value: any) {

   // ログインActionをdispatch
   this.store.dispatch(UserActions.login());
   // ユーザーID追加Actionをdispatch
   this.store.dispatch(UserActions.addUser({ userId: value.userId }));

   // 画面遷移
   this.router.navigate(['state']);
}
}

 

  • html

<form class="example-form" [formGroup]="sampleForm" (ngSubmit)="login(sampleForm.value)">
 <div fxLayout="column">
   <mat-form-field appearance="fill">
     <mat-label>ユーザーID</mat-label>
     <input type="url" matInput formControlName="userId" placeholder="userId" required>
     <mat-error *ngIf="sampleForm.controls.userId.hasError('integerValidator')">
      数字のみです
     </mat-error>
     <mat-error *ngIf="sampleForm.controls.userId.hasError('required')">
      ユーザーIDを入力してください
     </mat-error>
   </mat-form-field>

   <mat-form-field appearance="fill">
     <mat-label>パスワード</mat-label>
     <input type="password" matInput formControlName="password" placeholder="password" required>
     <mat-error *ngIf="sampleForm.controls.password.hasError('required')">
      パスワードを入力してください
     </mat-error>
   </mat-form-field>

   <button type="submit" mat-raised-button color="primary" [disabled]="!sampleForm.valid">ログイン</button>

 </div>
</form>

 

・customValidator

import { AbstractControl, ValidatorFn } from '@angular/forms';


const REG_INTEGER = /^[0-9]*$/

export function integerValidator(): ValidatorFn {
 return (control: AbstractControl): { [key: string]: any } | null => {
   // 値のチェック
   const result = !REG_INTEGER.test(control.value);
   // チェック結果を返却
   return result ? { integerValidator: { value: control.value } } : null;
};
}