10
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

4年目のアドベントカレンダー参戦になります。株式会社ピー・アール・オーです。
これまでに引き続き、今年も各自が興味のある分野について各々に書く方針で進めさせていただきます。

はじめに

angularでフォームを作成したときに無効だったボタンが一瞬だけ有効になるバグが発生し、原因を調べたところ非同期処理によるものだと分かったので以下にまとめる
参考:https://itnext.io/valid-and-invalid-in-angular-forms-61cfa3f2a0cd

Angularフォームの無効

Angualrのフォームボタンを無効にする一般的な方法はinvalidかvalidを使うかの2通りあります。
invalidとvalidの意味は

<button type="submit" [disabled]="form.invalid">送信</button> 


<button type="submit" [disabled]="!form.valid">送信</button>

この違いについて考えたことはありますか?
form.invalid と!form.valid? 論理的には同じはずですが、実際にはわずかな違いがあります。

これを実証するために、非同期処理を用いた単純なフォームを作成します。

検証

html
<form [formGroup]="form">
  <input type="text" placeholder="Enter your email" formControlName="email" />
  <button type="submit" [disabled]="!form.valid">送信</button>
  <div *ngIf="form.pending">
    <img src="https://www.benricho.org/loading_images/img-transparent/712-32.gif" />
  </div>
</form>

ボタンの無効化条件の違いを確認するだけなので非常にシンプルなフォームにしました。
フォームの送信ボタンは!form.validで非活性にするようにしています。

また、非同期処理中だとわかりやすいようにLodingのgifも表示するようにしています。

.ts ファイルでは、FormBuilder を使用してフォームを作成しました。
非同期処理を行うためにsetTimeout()を使用し、カスタムバリデーターに適用しています。

component
  form = this.fb.group({
    email: ['', [Validators.required, Validators.email], this.checkValidEmail]
  })

  constructor(private fb: FormBuilder) {}

  checkValidEmail(control: AbstractControl) {
    return new Promise(resolve => {
      setTimeout(() => {
        resolve(null)
      }, 2000)
    })
  }

これで準備ができたので実際にブラウザを見てみましょう。

実証

以下が送信ボタンの無効を[disabled]="!form.valid"にした場合になります。

!form.valid.gif
メールの入力後、処理中のロードが表示されロードが終了直後にボタンが有効になっています。
次に、送信ボタンの無効を[disabled]="form.invalid"にした場合も見ていきましょう。
form.invalid.gif
最初は送信ボタンが無効でしたがメールが入力されるとカスタムバリデーターの非同期処理が行われsetTimeoutで設定した2秒間送信ボタンは有効になっています。
このことから、invalidだと非同期処理中は falseを返していることがわかります。

以下にvalidinvalidの違いを図でまとめてみました。
valid.001.jpeg
短時間ボタンが有効になった理由は、vaildinvalidのpendingの違いにあります。

まとめ

[disabled]=”form.invalid”にした場合、フォームに非同期処理が存在するとボタンの無効が有効になったり予期せぬ動作があるので、フォームのボタンを無効にするには比較的安全な[disabled]=”!form.valid”を使用することをお勧めします。

10
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?