LoginSignup
8
2

stimulusでselect2変更時のchange actionを定義したい

Posted at

問題:select2のchangeイベントが呼ばれない

stimulusを使っているアプリケーション内でselect2を導入しようとした時の話です。
以下のように、都道府県のselect2の値が変更された時に市区町村を取得してくるような処理を書いていたのですが、なぜかfetchCitiesが呼ばれない。

hoge.html.slim
= f.select :prefecture_id,
            Prefecture.all.map { |p| [p.name, p.id] },
            { required: true },
            data: { 'hoge-target': 'prefectureSelectBox', action: "change->hoge#fetchCities" }
hoge_controller.js
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static targets = ['prefectureSelectBox']

  connect () {
    $(this.prefectureSelectBoxTarget).select2
  }

  fetchCities (e) {
    // 市区町村を取得する処理
  }
}

解決策:select2の変更時にchangeイベントを発火させる

そこで参考にしたのが以下の記事。
select2はネイティブイベントではなく独自のイベントを発火させているため、select2の独自イベントをキャプチャしてネイティブイベントを発火させるようにすれば良いとのことでした。なるほど。

問題は、Select2が'ネイティブ'イベントを使わないことだ。独自のイベントフレームワークを持っているのです。そのため、Select2イベントをキャプチャして、ネイティブイベントを再送信する必要があります。それがわかれば簡単だ!

上記を踏まえて修正したコードが以下になります。
select2変更時にネイティブのchangeイベントも発火されるようになるため、stimulusに設定したアクションが呼ばれfetchCitiesが実行されるようになりました。

hoge_controller.js
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static targets = ['prefectureSelectBox']

  connect () {
    $(this.prefectureSelectBoxTarget).select2
    // select2の独自イベントをキャプチャしてネイティブchangeイベントを発火
    $(this.prefectureSelectBoxTarget).on('select2:select', function () {
      const event = new Event('change', { bubbles: true })
      this.dispatchEvent(event)
    })
  }

  fetchCities (e) {
    // 市区町村を取得する処理
  }
}

8
2
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
8
2