▪️

AngularのsetErrorsで特定のエラーを削除する方法

に公開

はじめに

Angularでフォーム開発をしていると、こんな場面に遭遇したことはありませんか?

「特定の条件でのみ発生するバリデーションエラーを削除したいけど、
他のエラーは残しておきたい…」

Angularの標準的な setErrors() メソッドは、この要求を満たすのが意外と難しいのです。

よくある問題のシナリオ

例えば、商品検索フォームで「価格の範囲」を入力するケースを考えてみましょう。
ユーザーは検索条件として 最小価格(minPrice)最大価格(maxPrice) を入力します。

このとき、フォームには次のようなバリデーションが求められます:

  1. 両方とも必須入力(required
  2. 数値は 0 以上であること(min
  3. minPrice ≤ maxPrice でなければならない

問題のある実装

バリデーション要件の3つ目(minPrice ≤ maxPrice)は、2つの入力欄の関係をチェックするため、カスタムバリデーションが必要になります。そこで「条件を満たせばエラーを消す」という発想で、多くの開発者が最初に書いてしまうのが次のようなコードを書いてしまいます。

// すべてのエラーが削除される
if (minPrice <= maxPrice) {
  control.setErrors(null);
}

何が問題なのか?

setErrors(null) を呼ぶと、そのフィールドのエラーがすべて削除されます。

例えば、以下のように複数のエラーが同時に存在していた場合:

{ required: true, min: true, customError: true }

customErrorだけを消したかったのに、requiredmin まで一緒に消えてしまい、
結果として本来表示されるべきエラーメッセージが消えてしまいます。

なぜ setErrors(null) でエラーが消えるのか?

これはAngularのsetErrorsメソッドの仕様によるものです。

setErrors(
  errors: ValidationErrors | null,
  opts: { emitEvent?: boolean } = {}
): void

errors

  • ValidationErrors型を渡すと、それが現在のエラーとして設定されます。
  • null を渡すと「エラーなし」とみなされる

https://angular.jp/api/forms/AbstractControl#setErrors

解決策:特定のエラーのみを削除する

解決のポイントは次の3ステップです:

  1. 現在のエラーを取得する
  2. 消したいエラーだけを削除する
  3. 残ったエラーを再設定する(空なら null を渡す)

実装例

const errors = control.errors || {};
delete errors.customError;
control.setErrors(
  Object.keys(errors).length ? errors : null
);
// 結果:{ required: true, min: true } (必要なエラーは保持される)

おわりに

Angularでフォームバリデーションを扱う際、setErrors(null) を安易に使うと、
意図せず他のエラーまで消えてしまうことがあります。

ポイントは次の2つです:

  • setErrors既存エラーをすべて置き換える仕様
  • 特定のエラーだけ削除したい場合は 既存エラーを保持して再設定する

このパターンを理解しておけば、複雑なバリデーションでも安全にエラーを制御できます。

Discussion