メモ JavascriptHTMLjquery

label要素と関連付けされたinput要素にクリックイベントを付与すると2回実行される。

2021.04.30

こんにちはjunです。フォームとしての要素、ボタンとしての要素を掛け合わせて以下のようなものを作成していました。

<label class="c-button" for="form-input">
    <input data-product_id="1" id="form-input" type="checkbox" name="form-input" value="">
    <span class="text">まとめて購入</span>
</label>

<script>
    $('.c-button').on('click',function(){
        // ...
    })
</script>

labelをクリックするとチェックボックスにチェックが入り、さらにクリックイベントも走るという仕組みです。inputだけをクリックしても同じ動作になります。

しかしチェックをしてみると挙動が何故か変。私の場合はON・OFF的な処理をしていたので、inputをクリックすると正常に動き、labelだと処理が行われていないという現象に見舞われました。原因はタイトル通り、上記のような構成をjqueryで実装すると、labelをクリックすると$('.c-button')へのクリックイベントが2回走ることが原因です。対処としては3つほどあります。

1:changeイベントに変更する

input要素を活かしたい場合はこれがベストだと思います。changeイベントはinputなどの入力値が変更された時に発火するイベントです。for属性を用いてinputと関連付けされいるので、labelをクリックすることでinputの値(チェックされたか)を変更させることができます。一方でinputだけをクリックしても発火します。

なぜクリックイベントが2回起きるのかがわかりませんが、for属性あたりとかがなんか関係しているのかもしれません。 change属性であれば値が変更されたか否かでの発火条件となるので問題なくなります。

2:inputだけにする

$('.c-button')$('.c-button input')にします。そうすれば一応inputだけクリックした時に発火します。ただし、labelでボタンのスタイルを表現していたりする場合はこの手は微妙です。

3:inputでなくアイコン・画像にする

もしinputがフォーム送信的な意味をもたず実装しているならば(見た目だけ)、画像・アイコンで実装するというてもあります。その時はクラスを付与してアイコンを変えると言ったことが必要です。

まとめ

上記の解決法では1が一番ベストです。vanillajsで上記のような構成を作るとなぜか発生しないので、jqueryの仕様なのかもしれません。

Copyright © 2021 jun. All rights reserved.