🍑

バリデーションエラーとblur のタイミング

2021/05/30に公開

連結している Input はすぐにバリデーションエラーを出したくない

バリデーションエラーを出す時、 普通ならblur のタイミングですぐにエラーを出した方がユーザに優しい場合が多い。

でも電話番号とか郵便番号とか、複数の Input で一つの意味を持つ(*下記画像参照)時は連結している Input からフォーカスが外れた時にバリデーションエラーを出したい。Tabキーとかで連結した Input に移動する時はバリデーションエラーを出したくない。

という仕様にぶつかったのだが、自分はEventの理解がなかったので苦労した。

コードの例

    <form id="main-form">
      <input type="text" name="input1" placeholder="text input1" /> -
      <input type="text" name="input2" placeholder="text input2" /> -
      <input type="text" name="input3" placeholder="text input3" /> -
      <input type="text" name="input4" placeholder="text input4" />
      <button id="btn" onclick="clickBtn()">ボタン</button>
    </form>
    <div name="message"></div>
const state: string[] = ['', '', '', '']
const isIncludingEmpty = () => state.includes('')
const users = document.querySelectorAll('input[type="text"]')
const message = document.querySelector('div[name="message"]')
users.forEach((user, index) => {
  user?.addEventListener('focus', ({ target }) => {
    if (!(target instanceof HTMLInputElement)) return
    target.style.background = '#D9E8F6'
  })
  user?.addEventListener('blur', ({ target }) => {
    if (!(target instanceof HTMLInputElement)) return
    target.style.background = 'white'
    state[index] = target.value
  })
  // 上と一緒にできるけど力つきた
  user?.addEventListener('blur', (event) => {
    if (
      (event instanceof FocusEvent &&
        event.relatedTarget instanceof HTMLInputElement) ||
      !(message instanceof HTMLDivElement) ||
      message.textContent === null
    )
      return
    message.textContent = isIncludingEmpty() ? '全ての欄に入力してね' : ''
  })
})
const clickBtn = () => {
  alert(state.join('-'))
}

Event には value がないだのなんだの言われながら書いて勉強になった。

結果

Discussion