簡単Stimulus
この記事は ケーシーエスキャロット Advent Calendar 2023 の記事です。
先日お仕事でStimulusを扱う機会があり、 最初こそとっつきにくいと感じましたが、割とスムーズに理解することができました。 ちょうど良い機会なので、Stimulusの使い方をまとめてみようと思います。
と言っても基本的な使い方は Stimulus Handbook にまとまっているので、 この記事では実際に実装しながら使い方を簡単に振り返ってみようと思います。
注意
- この記事ではStimulusの導入方法は扱いません
作るもの
更新ボタンを押すと、APIから現在時刻を取得し、画面に表示する機能をStimulusで実装します。
イメージは以下です。
今回は段階を追って進めていきます。
準備
view と stimulus controller を用意します。
view
こんな感じのviewを用意します。
<div> <button>更新</button> <div> <%= Time.current %> </div> </div>
Stimulus controller
Stimulus の controller は bin/rails g stimulus
コマンドを使うと、Stimulus の controller ファイルの作成と、読込設定まで追加してくれます!(便利)
今回は update-button
という名前の controller を作成するので、コマンドは以下になります。
bin/rails g stimulus update_button
※update-button という命名はあまり適していないような気がしますが、スルーしてください。
作成された app/javascript/controller/update_button_controller.js
はこんな感じになっていると思います。
import { Controller } from "@hotwired/stimulus" // Connects to data-controller="update-button" export default class extends Controller { connect() { } }
1: 更新ボタンにクリックイベントを設定する
いきなり全てを実装するのも難しいので、まずは更新ボタンにクリックイベントを設定するところから。
更新ボタンをクリックすると alert ダイアログを表示するようにしてみます。
view と Stimulus controller を以下のように書き換えます。
<div data-controller="update-button"> <button data-action="click->update-button#update">更新</button> <div> <%= Time.current %> </div> </div>
export default class extends Controller { update() { alert("update!!!") } }
view の この部分。
<div data-controller="update-button"> <button data-action="click->update-button#update">更新</button>
一番上の div の data-controller
で適応させる Stimulus の controller を指定します。
※controller のファイル名は _
だが、controller 名としては -
を使うので注意
また、button には data-action
でイベントと、イベント発火時に実行する処理を設定しています。
この場合は、クリックイベント発火時に、 update-button
controller の update
というメソッドを実行する、という設定になります。
2: 更新ボタンクリック時に時刻表示を書き換えるようにする
次は実際に画面の表示を書き換えられるようにします。
更新ボタンをクリックすると、日時表示の要素の innerHTML
を「更新した!」という文字で更新します。
書き換え先の要素は getElementByID
などを使って取得することもできますが、
Stimulus には要素を参照するための target という属性があるのでこれを使います。
view と Stimulus controller を以下のように書き換えます。
<div data-controller="update-button"> <button data-action="click->update-button#update">更新</button> <!-- ここを書き換える --> <div data-update-button-target="area"> <%= Time.current %> </div> </div>
export default class extends Controller { // area という target を定義 static targets = ["area"] update() { this.areaTarget.innerHTML = "更新した!" } }
書き換え先の要素を area
という名前の target で指定させるようにしました。
この area
はどこを参照するかというのは view で、data-controller名-target
という属性で指定します。
<div data-update-button-target="area"> <%= Time.current %> </div>
area
target は controller 側で this.[target名]Target
とすると参照することができます。
この場合 this.areaTarget
で、area
targetに指定した要素が参照可能です。
3: APIから取得した値で時刻表示を書き換えるようにする
次は実際APIを呼び出して、取得した値で時刻表示を書き換えるようにします。
使用するAPIは、 /api/time/now
で呼び出すと、現在時刻をテキストで返してくれるものとします。
実装はこんな感じ。
class Api::TimeController < ApplicationController def now render plain: Time.current end end
API の URL は Stimulus controller 内に直接定義することもできますが、 またまた Stimulus には value という、値を受け渡すのに便利な属性があるので、 こちらを利用します。
view と Stimulus controller を書き換えます。
<div data-controller="update-button" data-update-button-url-value="/api/time/now"> <button data-action="click->update-button#update">更新</button> <div data-update-button-target="area"> <%= Time.current %> </div> </div>
export default class extends Controller { static targets = ["area"] // url という value を定義 static values = { url: String } update() { fetch(this.urlValue, { method: "GET" }) .then((response) => response.text()) .then((time) => this.areaTarget.innerHTML = time) } }
API の URL を url
というvalueで渡せるようにしました。
value が参照する値の指定も同様に view 側で行います。
値の指定は data-controller名-value名-value
という属性で行います。
<div data-controller="update-button" data-update-button-url-value="/api/time/now">
※ data-controller
と同じ要素に指定する必要があるので注意
url
value は controller 側で this.[value名]Value
とすると参照することができます。
この場合 this.urlValue
で、指定した API の URL が参照できます。
これで完成です!
まとめ
data-controller
で適応させる controller を指定data-action
で要素にイベントを設定できる- 他の参照したい要素は
target
、値を参照した場合はvalue
が使える