[Angular] 複数のcheckboxで一つ以上のチェックを必須とするバリデーション

AngularでWEB APの画面を作る際に、複数のチェックボックスをユーザに選択させることがよくあると思います。その際にcheckboxの未チェックをリアルタイムで検知する仕組みを作ることで、ユーザに余計な画面遷移やストレスを課さずに済み、不正なリクエストも防げます。

Angularにおけるcheckboxのバリデーション方法

A(単一のcheckbox向け) XX.invalidの利用

  • checkbox要素に以下の変更を加える

    • 属性値にrequiredを追加
      • チェックを必須とするバリデーションチェックが行われる
    • #で名前を付ける
      • ”#で付けた名称.invalid”でバリデーションエラーを検知可能になります
      • つまり、checkをしていなければ、以下のように状態値を確認できます
        1
        XXX,invalid=true
  • 送信button

    • 属性値 [disabled]= || XX.invalidで条件を追加する
    • XX.invalid=trueの時=チェックしていない時に、ボタンがdisabled=無効化される
  • 単一のチェックボックスのチェックを必須化するケースはこれで問題無さそう

    • Ex. 契約事項の確認画面

B(複数のチェックボックス向け) checkした項目を取得する配列が空か確認

  • checkboxの値を取得する配列が空であれば、ボタンをdisabledにする
  • 上記では”一つ以上にチェック”の検知が難しい
    • ngForでループで複数のチェックボックスを表示している場合、全てが必須になってしまう
  • 状態値の取り方以外はAと同様

今回は”複数のチェックボックスから最低一つ以上にチェックすること”を強制するため、Bの実装例を以下に示す

実装例

前提

実装

  • tsファイル側で先にbool値用の変数を宣言

    • check無しの時: true
    • check一つ以上の時: false
  • sample.component.ts

    1
    checkValidation = true;

一つ以上のチェックがあれば、上記の値をfalseに変更する仕組みが必要

  • buttonの無効化条件に追加

    • 一つでもtrueがあればdisabled(ボタンが無効化される状態)になる
  • sample.component.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <!--バリデーション状態によって無効化されるボタン-->
    <button mat-raised-button
    [disabled]="Id.invalid || passKey.invalid || this.checkValidation">

    <!--ついでにエラーメッセージも用意-->
    <mat-error *ngIf="checkValidation">最低一項目のチェックが必須</mat-error>

    <!--チェック時にtodoLeafItemSelectionToggle(node)という関数が発火する、チェックボックスをループ表示するサンプル-->

    <ngFor...
    <ng-container>
     <mat-checkbox
    [checked]="checklistSelection.isSelected(node)"
    (change)= "todoLeafItemSelectionToggle(node)"
    >{{node.name}}<!--dashboardにnode.nameの値を渡す (click)="onclickResource(node.name)"-->
    <!--click時にnode.nameを選択値として取得 マーキング--->
    </mat-checkbox>
    </ng-container>
    ...
  • 今回は配列(this.checklistSelection.selected)にチェックした値が入るように機能を作っている

    • ”this.checklistSelection.selected.length = 0”の時、つまり一つもチェックしていない時に、buttonを無効化すれば良い
  • 0をboolean値として扱ってくれるか試したがダメ

    • 0ならtrueにする関数が必要
    • check時にその関数を呼び出して値を変更したい
    • 初期値falseの変数を定義して、check時にtrueに変えるだけでOK
  • checkboxのソース

    • check時に値を取るメソッドを呼び出している
      • (change)= “todoLeafItemSelectionToggle(node)”
        1
        2
        3
        4
        5
        6
                 <mat-checkbox
        [checked]="checklistSelection.isSelected(node)"
        (change)= "todoLeafItemSelectionToggle(node)"
        >{{node.name}}<!--dashboardにnode.nameの値を渡す (click)="onclickResource(node.name)"-->
        <!--click時にnode.nameを選択値として取得 マーキング--->
        </mat-checkbox>
  • check時にチェック数に応じてbool値を変更する関数を定義

    • checkする度にchangeCheckboxValidation()を呼び出す
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/** Toggle a leaf to-do item selection. Check all the parents to see if they changed */
todoLeafItemSelectionToggle(node: FlatTreeNode): void {
this.checklistSelection.toggle(node);
this.checkAllParentsSelection(node);
// バリデーション用のbool値を取得する
this.changeCheckboxValidation();
}

// チェックボックスが一つでもチェックされていれば、bool値をfalseに変更するメソッド
changeCheckboxValidation(){
// check数が0出なければ、checkboxバリデーション用のbool値を変更
if (this.checklistSelection.selected.length != 0) {
this.checkValidation = false;
} else { // check数が0になったらtrueに
this.checkValidation = true;
}
}

以上で”最低一つにチェック”というバリデーションを実現できた

参考

Angular Mateerial関連記事

[Angular mat-input] バリデーションまとめ

  • Anuglarのフォームにおけるバリデーションチェックについてのまとめ

  • バリデーションチェックとは?

    • 最近のWEBサービスでよく見受けられる、リアルタイムで入力値をチェックして問題があればエラーを表示してくれる機能などのこと
      • レガシーなWEBサービスでは、半角、全角が間違っていても申請ボタンを押して更新するまで気づくことができず、ユーザがストレスを受けてしまうケースが多くありました
    • 活用例
      • 未入力の項目があれば、申請ボタンを無効化。該当箇所を赤くマーキング
      • 利用可能な型(Ex. 全角、半角、英数)を規定して制限
      • 文字数を制限
        • 悪意を持った攻撃を防ぐ効果があります
      • passwordを***でマスク
      • typeを規定
        • emailの@や郵便番号や電話番号のーが挟まる形式など

こういったバリデーションを用意に実装できるのがAngularの強みの一つ

Angularのmat-inputにおけるバリデーション

Angularにおいては、input要素に様々な属性値を与えることで、バリデーションチェックを行い、〜〜.valid/~~.invalidといった状態値で確認できる。以下に主なバリデーションパターンと解説を示す。

文字数制限

  • 文字数を強制
    • minlength=””
      • 指定した文字数以下の場合、入力欄がエラー状態になる(赤くなる)
    • maxlength=””
      • 指定した文字数までしか入力できない

必須入力

  • requiredをつけるだけ

typeの指定

  • type=で設定可能
    1
    <input type="email"...

パターンチェック

  • [PatternValidator]というディレクティブを利用することで、正規表現で詳細な条件を定める事ができる

  • 記法:pattern=”条件”

    • 以下は英字(小大)に限定している
      1
      <input name="XXX" ngModel pattern="[a-zA-Z ]*">
  • 英大文字+数字

    1
    <input pattern="[A-Z0-9]*">
  • 英(小,大)+数字(int)+記号

    1
    <input pattern="[a-zA-Z0-9!-/:-@¥[-`{-~]*">
  • ★正規表現を可視化してまとめたチートシート

エラーメッセージの表示

  • エラーメッセージの表示
    • mat-errorを使用
      1
      <mat-error *ngIf="条件"

ngIfで定める条件(バリデーションチェックに合格しているか?)は次項目を使うことが多い。

バリデーション状態の取得

  • テキストボックス(input)に#~~で名前を付ける事で以下の値を条件式で利用可能になる

    • バリデーション成功時:~~.valid
    • バリデーション失敗時:~~.invalid
  • エラーメッセージや最終的な送信ボタンにngIF=”~~.valid”を条件付けすることで、入力値に問題がある状態でのリクエストを未然に防ぎ、UXを向上させることができる

  • 条件が成り立たない時に無効化

    • ngIFではなく[disabled]=条件式を利用する
      1
      <button [disabled]="~~.invalid">ラベル</button>
  • 複数のバリデーションが通っている場合のみ有効化

    • 論理和演算子記号”||”で”または”とする
      1
      <button [disabled]="aaa.invalid||bbb.invalid">
  • 上記では各テキストボックスをひとつずつ条件付けしているが、form要素自体に以下のようにフォーム名を定めれば、全体のバリデータの状態をチェックできる(フォーム名.valid, フォーム名.invalid)

    • 項目が多い場合にはこちらの方が有効
      1
      <form #フォーム名="ngForm">

実装例

IDとパスワードを入力して送信ボタンの押下で認証を行う、基本的なフォームの例を以下に示す。

今回のサンプルにおける条件詳細

  • Id詳細

    • 未入力禁止
      • required
    • 最低文字数
      • minlength=”20”
    • 最大文字数
      • maxlength=”20”
    • 例の表示
      • placeholder
    • patternチェック
      • 英大文字+数字
        1
        pattern="[A-Z0-9]*"
    • エラーメッセージの表示
      • mat-error要素を使用
  • Password詳細

    • 未入力禁止
      • required
    • 最低文字数
      • minlength=”40”
    • 最大文字数
      • maxlength=”40”
    • 例の表示
      • placeholder
    • type
      • passwordで情報を秘匿
    • patternチェック
      • 英小大文字+数字+記号
        1
        pattern="[a-zA-Z0-9!-/:-@¥[-`{-~]*"
    • エラーメッセージの表示
      • mat-error要素を使用
  • Submitボタン

    • 各バリデートの中でエラーが一つでもあればボタンを無効化
      1
      [disabled]="Id.invalid || passKey.invalid"

実装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<!--フォームとバリデーション-->

<mat-form-field class="mat-input-margin1">
<mat-label>ID</mat-label>
<input matInput
id="Id"
akey="Id"
[(ngModel)]="akey"
minlength="20"
maxlength="20"
pattern="[A-Z0-9]*"
placeholder="Ex. BSCJJSH7333..."
required
#Id="ngModel"
>
<!--全バリデーションチェック成功時にId.validが成り立つ--->
<mat-error>入力必須</mat-error>
</mat-form-field>

<mat-form-field class="mat-input-margin2">
<mat-label>Password</mat-label>
<input matInput
id="passKey"
skey="passKey"
[(ngModel)]="skey"
minlength="40"
maxlength="40"
pattern="[a-zA-Z0-9!-/:-@¥[-`{-~]*"
placeholder="Ex. Hy2D3..."
type="password"
required
#passKey="ngModel"
>
<mat-error>入力必須</mat-error>
</mat-form-field>

<!--上記のフォームの入力値のバリデーションチェック成功時に有効化される送信ボタン-->

<button mat-raised-button
(click)="submit()"
[disabled]="Id.invalid || passKey.invalid"
>Submit</button>

その他のAngular Materialについては以下にまとめています。

参考

関連記事

その他

[Angular Material入門] mat-inputで生成したフォームから入力値を取得(双方向データバインディング)

Angular初級者向けに、簡単なフォームを生成して入力値を取得するまでを解説します。

基礎知識

前提となる超基本なので分かっている部分は飛ばしてください。

Angular Projectの初め方

  • Angular Project
    • Angularにおけるアプリの雛形/単位のことです
  • Angular PJを生成
    1
    ng new "ap-name"
  • Componentを生成
    • APはコンポーネントと呼ばれる一塊で開発していきます
      1
      ng g component "component-name"
    • コンポーネントは以下のファイルのセットです
      • HTML/Typescript/Scss/karma
    • HTMLが画面、Typescriptが機能、Scssがデザイン、karmaがテスト用ファイルというイメージです

Angular Material

  • Angular Material

    • Googleが提唱しているMaterial DesignというCSSフレームワークを使うためのツール
      • Google/twitter/Microsoft等は、AngularでWEB APを開発しているので、それらのデザインに使われています
    • 要するにAPの画面の部品を、デザイナーでなくとも簡単に作れるようになるツールです
    • 様々なMaterialを組み合わせてパズルのようにUI(画面のこと)を開発していくのがAngular開発の基本です
  • 使用例

  • 設定を覚えれば、上記の様なmaterialをhtmlに1行書くだけで表示できます
    • つまり、これらを順にマスターしていけば、APの画面を自在に作れます

mat-input

  • Angular Material mat Input
    • 今風のフォーム(入力欄のこと)を作れます
    • HTMLに<input mat-input></input>と一行書くだけで、インターネット黎明期のようなフォームにならずに済みます
    • 他にも色々と便利な機能があります
      • オートコンプリート機能
        • 入力途中で予測表示してくれる機能
        • AngularもGoogleが作っているだけあって、ブラウザの記憶機能も使えます
      • プレイスホルダー機能
        • 入力欄に未記入の状態のみ、うっすら案内を表示してくれる機能
        • 記入例をこれで表示するとイケてるAPっぽく見えます
      • バリデーション機能
        • typeの指定
          • 例えば mail にすれば自動的にmailの英数で@を挟む形式以外入力できなくなります
          • 電話番号や郵便番号であれば、自動的に-を補完してくれたりもします
        • 読み込みを挟まないエラー表示
          • 条件を定めると、入力中にリアルタイムでエラー表示等できます
          • 全入力して送信を押すまでエラーが出ないWEBページでイライラしたことありませんか?こういったUX(ユーザ体験)に配慮することでモダンなAPを開発しましょう。例えば、大文字小文字は自動で変換するか先に警告しましょう。

mat-input example

双方向データバインディング

  • 双方向データバインディング
    • html側とts側で変数を自動的に同期することが可能です
  • 記法
    1
    [(ngModel)]="variable-name"

実装

Angular Materialのinstall

  • 以下のコマンド一発で利用の準備が整います
    1
    $your-angular-pj> ng add @angular/material
  • 質問に対しては全てYesでOK
    • 途中でアプリケーションの主要カラーとサブカラーを聞かれます
    • 左が主要カラー/右がサブカラーです

html

  • 実装例を以下に示します
    • input要素にmatInputを属性として書くだけでangular material仕様のフォームになります
    • [(ngModel)]=”key”
      • 双方向データバインディングで、ts側と変数keyを共有しています。入力値が自動的に変数keyに代入されます
    • NaNで変数の値を表示できます
      1
      2
      3
      4
      5
      <mat-form-field>
      <mat-label>KeyId</mat-label>
      <input matInput id="KeyId" key="KeyId" [(ngModel)]="key" min="1" placeholder="Ex. abc..." >
      </mat-form-field>
      {{key}}

ts

  • 変数を宣言するだけでOK
    1
    2
    // 入力値を格納する変数を宣言
    key;

mat-inputにバリデーションを実装する

  • 次に今回作ったフォームに”バリデーションチェック”を実装しましょう

  • バリデーションチェックとは?

    • 最近のWEBサービスでよく見受けられる、リアルタイムで入力値をチェックして問題があればエラーを表示してくれる機能などのこと
      • レガシーなサービスでは、半角全角が間違っていても申請ボタンを押して更新するまで気づくことができず、ユーザがストレスを受けて利用を諦めてしまうことも
    • 活用例
      • 未入力の項目があれば、申請ボタンを無効化。該当箇所を赤くマーキング
      • 利用可能な型(Ex. 全角、半角、英数)を規定して制限
      • 文字数を制限
        • 悪意を持った攻撃を防ぐ効果があります
      • passwordを***でマスク
      • typeを規定
        • emailの@や郵便番号や電話番号のーが挟まる形式など

おまけ:未入力の場合のみ初期値を表示するロジックを開発する

  • ts側に以下の様な判別ロジックを書きます
    • 入力値の有無をif(this.key === undefined)で判断しています
      1
      2
      3
      4
      5
      6
      7
      // 入力値を格納する変数を宣言
      key;

      // 判別ロジック
      if ( this.key === undefined ) {
      this.key = '初期値';
      }

以上です。Angular APのUI(画面)開発はAngular Materialのページで必要そうなMaterialを探して、使い方をググりながら進めていくというイメージを持てればある程度自走できるようになると思います。
Angular Materialについて、公式ドキュメントだけでは難しいものは記事に解説をまとめているので、参考にどうぞ。

参考

関連記事

その他

@EventEmitter @Input @Output @ViewChild ACM AMP API Gateway AR AR.js AR.js Studio AWS AWS Amplify AWS Budgets AWS Cost Explorer AWS SDK for JavaScript AddThis Adobe XD Alexa Amazon CloudWatch Amazon Honycode Amazon SNS Android Angular Angular Material AngularFire AppSync Augury C CDN CI/CD Cloud Craft Cloud9 CloudFormation CloudFront CloudTrail Cognito Cost Anomaly Detection Cubase ai Cubasis LE DTM Disqus DynamoDB Elgato HD 60S Firebase Firebase Hosting Former2 Github Github Actions Github.com GithubEnterprise GithubPages Google Chrome Google Cloud Shell GraphQL Hexo Hosting IAM Ionic JSON JavaScript LadioCast Logging LowCode MFA MS Authentication MacBook Pro 16 Mind Node NETDUETTO Netflix Party Netlify Network NoCode Observable PO PdM Promise RPA ReactiveForm Recognition Route53 S3 SAM(Serverless Application Model) SAR SSL SYNCROOM Schematics ScrumInc Serverless Service Siri Sitemap Spark AR Steinberg UR44C Teams Touch Cast Studio Treetable TypeScript UI UI Bakery WAF WAFv2 WEB Page Dev WEB会議 WebAR WebSocketAPI Webhook Windows Power Automate Wireshark aot async/await aws config cloud9 display.land draw.io e2e test filter() forkJoin() google search console hexo-generator-amp iOS iPad Pro iPhone icarus map() mat input mat tree mat-checkbox mat-input mat-selection-list mmhmm ngFor plantUML popIn Aladdin2 then() vscode ”global is not defined” らくがきAR アジャイル アジャイル開発 クロスプラットフォーム ショートカット スクラム スクラム開発 テレワーク ファイル操作 ブラウザ型IDE プロダクトオーナー プロダクトマネージャー プロトタイピング リモートセッション 共同開発 双方向データバインディング 待ち合わせ処理 認定スクラムマスター 静的WEB Hosting 静的WEBサイトHosting
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×