コード例
ここで作るのは下記のようなUIです。
デモはこちらに用意しています。
class属性を変更するので十分でしょう<div> <h2 class="text-4xl pb-8 border-b border-gray-300"> Frequently Asked Questions </h2> <%= render 'accordion_row', title: "吾輩は猫である。名前はまだ無い。" do %> どこで生れたかとんと見当けんとうがつかぬ。何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。吾輩はここで始めて人間というものを見た。 <% end %> <%= render 'accordion_row', title: "この書生の掌の裏でしばらくはよい心持に坐っておった" do %> ふと気が付いて見ると書生はいない。たくさんおった兄弟が一疋ぴきも見えぬ。肝心かんじんの母親さえ姿を隠してしまった。その上今いままでの所とは違って無暗むやみに明るい。眼を明いていられぬくらいだ。はてな何でも容子ようすがおかしいと、のそのそ這はい出して見ると非常に痛い。吾輩は藁わらの上から急に笹原の中へ棄てられたのである。 <% end %> <%= render 'accordion_row', title: "吾輩の主人は滅多めったに吾輩と顔を合せる事がない" do %> 職業は教師だそうだ。学校から帰ると終日書斎に這入ったぎりほとんど出て来る事がない。家のものは大変な勉強家だと思っている。当人も勉強家であるかのごとく見せている。しかし実際はうちのものがいうような勤勉家ではない。 <% end %> </div>
accordion_row partialを切っています
do endブロックとyieldを使って、コードをスッキリさせています。この使い方はRails Guideでも紹介されていますaccordion_row partial<div class="py-4 border-b border-gray-300" data-controller="accordion" data-accordion-toggle-switch-class="rotate-180"> <h3 class="flex justify-between text-xl cursor-pointer"> <span><%= title %></span> <div data-accordion-target="switch" data-action="click->accordion#toggle" class="pt-2 transition-all duration-300"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6"> <path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5"/> </svg> </div> </h3> <div data-accordion-target="revealable" class="h-0 overflow-hidden transition-all duration-300 text-sm"> <div class="mt-4"><%= yield %></div> </div> </div>
data-accordion-target="revealable"となっているところが、アコーディオンの開閉で見え隠れする箇所です
data-accordion-target="revealable"なので、Stimulus controllerから制御される箇所ですhiddenで隠す訳にはいきません。h-0 overflow-hiddenで隠して、徐々に大きくなるアニメーションができるような隠し方をしていますdata-controller="accordion"となっているところで、accordion Stimulus controller(後述)に接続します
data-accordion-toggle-switch-class="rotate-180"のところは、アコーディオンを開閉させたとり、ボタンをどのように変化させ、ユーザにフィードバックを与えるかを記しています。ここでは180度回転させますdata-accordion-target="switch" data-action="click->accordion#toggle"のところはアコーディオン開閉ボタンです
data-action="click->accordion#toggle"は、「クリックしたらaccordion controllerのtoggle()メソッドを実行すること」という意味です。イベントハンドラになりますdata-accordion-target="switch"は、ここがStimulus controllerから制御される箇所だと示しています。アコーディオン開閉時に矢印を回転させるためですStimulusはこのようにHTMLをcontrollerに接続します。大きく、2つの指定をしています
import {Controller} from "@hotwired/stimulus" // Connects to data-controller="accordion" export default class extends Controller { static targets = ["revealable", "switch"] static classes = ["toggleSwitch"] connect() { } toggle(event) { this.#toggleRevealableTargets() this.#toggleSwitchTargets() } #toggleRevealableTargets() { this.revealableTargets.forEach(target => { /* * CSS transitions cannot transition if the destination height * is not explicitly specified (like height: auto). * Hence, we get the scrollHeight with JavaScript and * explicitly set that value as the destination height. * */ if (parseInt(target.style.height)) { target.style.height = 0 } else { const scrollHeight = target.scrollHeight target.style.height = scrollHeight + "px" } }) } #toggleSwitchTargets() { this.switchTargets.forEach(target => { target.classList.toggle(this.toggleSwitchClass) }) } }
connect() {}メソッド定義があります。これはbin/rails g stimulus [controller名]をやると自動的に作ってくれるもので私はそのまま残すことが多いです
alert('hello')ってやるとcontrollerがちゃんとHTMLと繋がったことがわかりますので、Stimulusを使う第一歩で私は必ずこの確認をしていますstatic targets =, static classes =を使って、先ほどHTMLで指定したdata-accordion-target="switch", data-accordion-target="revealable"やdata-accordion-toggle-switch-classと接続します。この辺りは公式ドキュメントに記載されていますのでご確認くださいtoggle()だけです。data-action="click->accordion#toggle"によって呼ばれます。