中安拓也のブログ

プログラミングについて書くブログ

【Angular】 ボタンの連打を防止するディレクティブを作る(連続クリック・二重送信の禁止)

はじめに

アプリケーションを作る上で避けられない、ボタンの連続クリック防止機能を今回は作成します。この機能がないと同じメールが2通飛んだりデータベースにレコードが重複してINSERTされてしまうかも......

バージョン情報

JavaScriptのフレームワークとしてAngularを使用しています

  • Angular@7.0.6
  • typescript@3.1.6
  • webpack@4.19.1

実装

今回のテーマである連続クリックの防止ですが、ディレクティブを使用して実現します。
AngularのディレクティブにはNgForとNgIfに代表される構造ディレクティブとテンプレート要素の属性を変更する属性ディレクティブがあり、今回作成するのは後者の属性ディレクティブになります。

ボタンの連打を防止するAngularのディレクティブ

このディレクティブの機能としては、HTTP通信(非同期処理)が発生するボタンでの使用を想定していて、押下したときにHTTPの通信が終わるまで、ボタンを連打されないように非活性化するといったものになっています。

今回作成したディレクティブの処理の流れ

  1. ElementRefを通してボタンのHtmlElementを取得する
  2. @HostListener('click')でボタンがクリックされたイベントを検知し、ボタンを非活性化(disabled)する
  3. HTTP通信が終了したことを@Inputデコレーターを通して検知したら、ボタンの非活性化を解除する

HTMLからディレクティブを呼びだす

引数を受け取るタイプのディレクティブなので、このようにHTMLテンプレート上で引数を渡してあげる必要があります

今回作成したディレクティブの呼び出し例

終わりに

スピナー(くるくる回るやつね)使えばよくねえか???と思った人もいるかもしれませんが、デザイン的にスピナーを使えない事情があったのでボタンを非活性にする方法でやってみました。
あと0.5秒とか1.0秒とか追加で非活性の時間のばしてるけど(エクセルを信頼せずに電卓で計算をやり直す側の人間なので)、完全に無駄な処理だったかもしれない。せっかくHTTP通信中のフラグをInputで渡しているわけだしそのフラグのON・OFFだけでボタンの非活性・活性を制御しても良かった気がしています