仕事で、とあるRailsアプリを作っているのですが、そこでstimulusを採用していました。そうしたらちょうど少し前にstimulusのバージョン2.0.0がリリースされていました。このバージョンアップによって、かなり書きやすくなりました。
今までと何が違うのか?
今までは、コントローラーを指定してから、そのコントローラーのターゲットを指定するのが面倒でした。
before
<div data-controller="vote"> <button type="button" data-target="vote.button">投票</button> </div>
after
属性名だけでどのコントローラーのターゲットか分かるので読みやすくなりました。
<div data-controller="vote"> <button type="button" data-vote-target="button">投票</button> </div>
新しく追加された機能
大きく変わる機能が、Value API と CSS Class APIです。
Value API
Value APIは、そのまんまですが、値を持つことができます。 stimulusの公式サイトのリファレンスから引用しますと、以下のような感じです。
html
<div data-controller="loader" data-loader-url-value="/messages"> </div>
import { Controller } from "stimulus" export default class extends Controller { static values = { url: String } connect() { fetch(this.urlValue).then(/* … */) } }
この例だと、fetchする先のURLをValue APIで変えることができる、という感じです。valueの指定は、Hashのキーにvalueの名前を、値に型を書きます。そうすると、読み込んだ際に型に沿った形にキャストしてくれます。
これだけだと、値を渡せるようになっただけ?という感じですが、それだけではありません!Value APIは、値が変わった時にコールバック関数が呼ばれます。 CodePenで、Value APIと、そのコールバックを使って、送信ボタンの状態制御をしてみました。
See the Pen stimulus v.2.0.0 sample(Value API) by patorash (@patorash) on CodePen.
stimulusのコントローラーでinitialize, connect, disconnectの3つのメソッドが自動でコールバックされます。今回はこれらも使って、
- connectのタイミングでコメント入力エリアにinputのイベントリスナを定義する。
- 入力されたら、handleEventメソッドでイベントを拾い、入力エリアに1文字以上あったら、
enableValue
をtrueに変更。0文字ならfalseに変更。 enableValue
の値が変わったらenableValueChanged
メソッドがコールバックで呼ばれ、submitボタンのdisabledの状態が変わる!- disconnectのタイミングでイベントリスナを解除する。
という仕組みになっています。valueはhtmlの要素の属性として値がある状態なので、戻るボタンなどで戻った時は再びconnectが呼ばれてちゃんと動く、というわけです。
私的には非常にわかりやすくていいなぁ!と思いました。
4時を過ぎたので、今日はこの辺りまでにして、続きのCSS Class APIはこの記事に追記していきます。
続きを書いていきます!
CSS Class API
CSS Class APIは、stimulusで使うCSSに名前をつけることができる機能です。 stimulusの公式サイトのリファレンスから引用しますと、以下のような感じです。
// controllers/search_controller.js import { Controller } from "stimulus" export default class extends Controller { static classes = [ "loading" ] loadResults() { this.element.classList.add(this.loadingClass) fetch(/* … */) } }
html
<form data-controller="search" data-search-loading-class="search--busy"> <input data-action="search#loadResults"> </form>
アクションのloadResults
メソッドを呼び出したら、searchコントローラーの紐づいたformのcssに.search--busy
を追加します。
以前までは、クラス名をJavaScriptにハードコーディングしなければいけませんでした。
// 以前のstimulus // controllers/search_controller.js import { Controller } from "stimulus" export default class extends Controller { loadResults() { this.element.classList.add('search--busy') // => ハードコーディング fetch(/* … */) } }
これだと、CSSのクラス名が変わった場合にstimulusのコードに修正が必要になっていました。しかし、CSS Class APIの登場により、HTML側の修正だけでよくなりました。
CSS Class APIが活用できる具体的なシーン
例えばBootstrapのバージョンが上がったときを例にしましょう。
未だにBootstrap3を使い続けている環境があるとします(私の担当プロジェクトですが…)。そこでは、要素を隠すためのCSS Class名は、.hidden
です。
Bootstrap3を使っているフォーム
<div data-controller="comment" data-comment-close-class="hidden"> <button type="button" data-action="comment#openForm">コメントする場合は押してください</button> <form class="hidden" onSubmit="return false" data-comment-target="form"> <input type="text" name="content"> <input type="submit" value="送信"> <button type="button" data-action="comment#closeForm">キャンセル</button> </form> </div>
// controllers/comment_controller.js import { Controller } from "stimulus" export default class extends Controller { static targets = [ "form" ] static classes = [ "close" ] openForm() { this.formTarget.classList.remove(this.closeClass) } closeForm() { this.formTarget.classList.add(this.closeClass) } }
これをBootstrap4にバージョンアップします。
data-comment-close-class="d-none"
と、<form class="d-none">
に修正します。
<div data-controller="comment" data-comment-close-class="d-none"> <button type="button" data-action="comment#openForm">コメントする場合は押してください</button> <form class="d-none" onSubmit="return false" data-comment-target="form"> <input type="text" name="content"> <input type="submit" value="送信"> <button type="button" data-action="comment#closeForm">キャンセル</button> </form> </div>
stimulus側のコードは、変更することは何もありません!
このように、CSS Frameworkに依存しない形でJavaScriptのコーディングが可能になりました。
まとめ
stimulusが登場した時点でも、すごい!とは思っていたのですが、バージョン2になって、さらに使いやすくなりました!Value APIの登場で、他のMVVMライブラリのcomputedみたいなことがやりやすくなりましたし、CSS Class APIの登場で、CSS Frameworkに依存しないコーディングができるようになりました。
最近のフロントエンドとバックエンドを疎結合にしていく流れも、もちろんいいとは思いますが、少々(かなり?)複雑です。Railsで簡単なものを簡単に実装しやすいという点では、stimulusは最高のパートナーになってくれると思います。