Stimulusでコントローラー間のデータやりとり

Stimulusでコントローラー間のデータやりとりはどうすればいいのか?

調べてみるとカスタムイベントを使う手法が紹介されていた。

Communicating between Stimulus controllers using custom events

リンク先のコードが十分小さいので理解しやすいが、「+1」ボタンをクリックすると結果に足される例。

ボタンと結果が別のコントローラーである。

HTMLではボタンにcountupコントローラーを割り当て、クリックするとcountupコントローラーのclickメソッドが呼び出される。その結果カスタムイベントplusoneが発信される。

一方resultコントローラーはplusoneイベントをupdateメソッドで処理するようになっている。

<button data-controller="countup" data-action="click->countup#click">+1</button>

<div data-controller="result" data-action="plusone@window->result#update"></div>

clickメソッドでカスタムイベントを作ってdetailプロパティに渡したい値を設定する。そしてdispatchEventでカスタムイベントを発信。

// countup_controller.js
import { Controller } from "stimulus"

export default class extends Controller {
  click() {
    const event = new CustomEvent('plusone', { detail: 1 })
    window.dispatchEvent(event);
  }
}

上記のカスタムイベントのdetailプロパティを好きなように処理する。この場合は合計に足して、HTMLに結果を表示するようにしている。

// result_controller.js
import { Controller } from "stimulus"

export default class extends Controller {
  initialize() {
    this.sum = 0;
    this.element.innerHTML = this.sum;
  }

  update(event) {
    if (event.detail) {
      this.sum += event.detail;
      this.element.innerHTML = this.sum;
    }
  }
}

カスタムイベントすごい便利で簡単!という印象だが、これ以上複雑になったらどうしようという心配もある。

一覧へ戻る