これまでの記事で入門と、よりよい実装方法について説明しました。
今回からはより実践的なControllerを作っていきたいと思います。
手始めにDisclosureを作りましょう。
Disclosureとは
details-summary要素のように折りたたみ可能なUIのことです。
ソシオメディアさんで詳細に説明がされています
Disclosureに求められる要件
- トリガー要素をクリックするとディスクロージャーが開き、再度クリックすると閉じる
- 開いてるかどうかをaria-expandedでスクリーンリーダー等に知らせる
HTMLを書いてみる
<div class="Note Note--close">
<button type="button"
class="Note__trigger"
aria-controls="note__contents"
aria-expanded="false"
>年末年始の営業について</button>
<div class="Note__content" id="note__contents">
<p>12月28日から翌年1月6日まで休みます。</p>
<p>尚、その間はネット販売も休止しておりますのでご了承ください</p>
</div>
</div>
trigger要素に使役する要素をaria-controlsで指定し、開閉状態をaria-expandedで説明します。
次はこれにStimulusで振る舞いをアタッチしていきましょう。
Disclosure Controllerを書く
button要素にdata-actionで振る舞いをもたせ、.Note--hideクラスの付け替えとbutton要素のaria-expandedの更新を行うだけです。
app.register('disclosure', class extends Controller {
static targets = ['trigger'];
static classes = ['hide'];
toggle(evt) {
let isClose = this.element.classList.toggle(this.hideClass)
this.triggerTarget.setAttribute('aria-expanded', String(!isClose));
}
})
最低限、こんな感じの実装でよいでしょう。
See the Pen QIITA_STIMULUS_DISCLOSURE by nazomikan (@nazomikan) on CodePen.
details要素のopen属性のように状態をHTMLのattributeに持たせるのもよいかもしれません。
その場合はvalues apiを用いるとよいでしょう。
ここで作られたControllerはDOMの情報を密にもっていないため、非常に再利用性の高いパーツとして使えます。
違うclassで開閉を制御してる場合も、HTML側のdata-disclosure-hide-class
の値をそのclassに指定すればJavaScriptコードはそのまま再利用可能になります。