はじめに
電話番号のように文字数が多いものがあっているかは確認しにくいです。なので、3桁、4桁区切りでハイフン(-)を入れます。自らハイフンを入れてもいいですが、自動でハイフンが入る方がいいです。電話番号があっているかだけに注意を向けられるからです。
そこで、HotwireのStimulusを使って、電話番号が自動フォーマットされるようにしました。
環境
- Rails 7.0.7
- Ruby 3.2.2
実装
電話番号を入力する<input>
要素に入力があるたびに、フォーマットが自動で実行されるようにします。
自動フォーマットのためのstimulus controllerを作成します。
import { Controller } from '@hotwired/stimulus'
import { PhoneNumberUtil, PhoneNumberFormat } from 'google-libphonenumber'
// Connects to data-controller="phone-number"
export default class extends Controller {
format() {
if (this.element.value.length > 1) {
const phoneNumberUtil = PhoneNumberUtil.getInstance();
const region = 'JP';
const number = phoneNumberUtil.parseAndKeepRawInput(this.element.value, region);
this.element.value = phoneNumberUtil.format(number, PhoneNumberFormat.NATIONAL);
}
}
}
google-libphonenumber は、電話番号のパース、フォーマットなどができるpackageです。このpackageを使って、電話番号をフォーマットしています。
format
メソッドが実行されれば、data-controller="phone-number"
属性を持ったHTML要素のvalue
が日本国内の電話番号の形式にフォーマットされます。
以下のように<input>
要素にdata-controller="phone-number"
属性、data-action="phone-number#format"
属性を持たせれば、入力のたびに自動でフォーマットされます。format
メソッドはinput
イベントが発生するたびに実行されています。これは<input>
要素にdata-action
属性を持たせていて、<input>
要素のデフォルトイベントがinput
だからです。メソッドを実行するイベントをinput->phone-number#format
のように明示的に指定することもできます。詳しくは、リファレンスを参照ください。
= simple_form_for user do |f|
= f.input :name
= f.input :annual_income
= f.input :phone_number, input_html: { 'data-controller': 'phone-number', 'data-action': 'phone-number#format' }
= f.submit class: 'btn btn-primary'
まとめ
HotwireのStimulusを使って、電話番号が自動フォーマットされるようにしました。
同じようなことを愚直にやろうとしたら、以下のようなことをすると思います。
- HTML要素のidをもとにHTML要素を取得する
- 取得した要素に対してEventListenerを作る
- EventLinstenerで指定したイベント発生時の処理を作る
そのため、HTMLを見ただけでは、どのイベントで何が実行されるのかはJavaScriptファイルをみないとわかりません。
一方、Stimulusではdata-action
で、どのイベントでどのメソッドを実行するのかHTML上で指定できます。そのため、HTMLを見ただけでも、どのイベントでどのようなメソッドが実行されるのか分かり易いです。
ただ、その分かり易さを高めるためには、stimulus controllerの名前や、メソッド名を直感的なものにする必要があります。どんな時でも結局、命名の難しさに直面するのが面白いところです。