Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Hotwire を使って管理画面を簡単にプチSPA化する - Kaigi on Rails 2023
Search
Takaharu Yamamoto
October 29, 2023
Programming
2
970
Hotwire を使って管理画面を簡単にプチSPA化する - Kaigi on Rails 2023
https://kaigionrails.org/2023/talks/yamataka/
Takaharu Yamamoto
October 29, 2023
Tweet
Share
Other Decks in Programming
See All in Programming
Go1.23で入った errorsパッケージの小さなアプデ
kuro_kurorrr
2
390
ドメイン駆動設計を実践するために必要なもの
bikisuke
4
330
Architecture Decision Record (ADR)
nearme_tech
PRO
1
680
長期運用プロダクトの開発速度を維持し続けるためのリファクタリング実践例
wataruss
8
2.7k
LangChainの現在とv0.3にむけて
os1ma
4
910
Rechartsで楽にゴリゴリにカスタマイズする!
10tera
1
170
令和トラベルにおけるLLM活用事例:社内ツール開発から得た学びと実践
ippo012
0
140
月間4.5億回再生を超える大規模サービス TVer iOSアプリのリアーキテクチャ戦略 - iOSDC2024
techtver
PRO
1
900
私のEbitengineの第一歩
qt_luigi
0
450
Using Livebook to build and deploy internal tools @ ElixirConf 2024
hugobarauna
0
250
仮想ファイルシステムを導入して開発環境のストレージ課題を解消する
segadevtech
2
540
Why Prism?
kddnewton
4
1.7k
Featured
See All Featured
Fashionably flexible responsive web design (full day workshop)
malarkey
401
65k
Build your cross-platform service in a week with App Engine
jlugia
228
18k
GitHub's CSS Performance
jonrohan
1029
450k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
227
52k
Bash Introduction
62gerente
608
210k
Raft: Consensus for Rubyists
vanstee
135
6.5k
A Modern Web Designer's Workflow
chriscoyier
691
190k
Side Projects
sachag
451
42k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
157
15k
What’s in a name? Adding method to the madness
productmarketing
PRO
21
3k
Automating Front-end Workflow
addyosmani
1365
200k
Web Components: a chance to create the future
zenorocha
308
42k
Transcript
Hotwire を使って 管理画⾯を簡単にプチSPA化する Takaharu Yamamoto Kaigi on Rails 2023
⾃⼰紹介 • ⼭本孝春 • GitHub: yamataka22 • 個⼈事業主 • 中⼩規模システムの受託開発をしてます
• Railsで⼀気通貫した開発が好き
Hotwire 使ってますか?
Hotwire 使ってますか? 情報が少ない 実績が少ない とりあえず無効化
Hotwire 使ってますか? 情報が少ない 実績が少ない とりあえず無効化 Turbolinksの⼆の舞に...?!
本⽇のテーマ Hotwireを使って管理画⾯をモーダル化する →この説明を通じて、Hotwireの敷居を下げたい
• 話すこと ◦ HotwireでModalを扱う⽅法を、コードを例⽰しながら実践 レベルで説明します • 話さないこと ◦ 時間の都合上、Hotwireの⼊⾨的な内容(TurboFrameとは 何か?など)は割愛します
今⽇の内容
管理画⾯にモーダルを 使うメリットは? そもそも
よくある画⾯遷移 ⼀覧で検索をして、⾏を選択
よくある画⾯遷移 詳細画⾯に遷移する
よくある画⾯遷移 そこから⼀覧に戻ると indexのPath
よくある画⾯遷移 検索状態がリセットされてしまう
よくある対策 • ブラウザの別タブで表⽰ ◦ assetsを含めた画⾯全体をリロードするので重い ◦ 気づいたらブラウザがタブだらけ • 戻るボタンに検索条件のパラメータを保持 ◦
戻るだけなのに再度検索が⾛る ◦ スクロール位置などは保持されない
⼀覧からの遷移をモーダルで開けば
⼀覧の状態を維持できる
モーダル表⽰のメリット • 画⾯の状態を維持しながら操作を進められる • モーダル内だけ描画するので、挙動が軽い • ユーザーはその画⾯に留まれる安⼼感がある
ただし管理画⾯なので • 開発にそこまでコストをかけたくない • サーバーサイド側のエンジニアだけで UIも含めて実装することが多い
ただし管理画⾯なので • 開発にそこまでコストをかけたくない • サーバーサイド側のエンジニアだけで UIも含めて実装することが多い モーダルのために作り込むことは避けたい
そこで Hotwire
Hotwireなら • ほとんどJavaScriptを書くことなく • ⼀般的な画⾯遷移版に少し⼿を⼊れるだけで • 簡単にモーダル化できる
コードの説明の前に • モーダルの描画にはBootstrapを利⽤します ◦ Bootstrap以外でも、JavaScriptを使ってモーダル表⽰の制御ができれ ば、他のツールでも代替可能です • 時間の都合上、細かな部分は説明を省略します ◦ 本⽇説明するコードはGitHubで公開してます
github.com/yamataka22/kaigionrails2023-admin-modal
やること 1. TurboFrame + Stimulus でモーダルを開く 2. TurboStream で登録後の描画を切り替える 3.
ブラウザのURLを追随させる
やること 1. TurboFrame + Stimulus でモーダルを開く 2. TurboStream で登録後の描画を切り替える 3.
ブラウザのURLを追随させる
モーダル表⽰のポイント • TurboFrameを使って、モーダル部分のHTMLの破⽚を⽣ 成する • その破⽚がブラウザに読み込まれたタイミングで、 Stimulusのインスタンスを⽣成し、connect()を経由して モーダルを開く
app/views/application/_remote_modal.html.erb Modal表⽰のerb (TurboFrame)
app/views/application/_remote_modal.html.erb 中⾝はBootstrapの⼀般的な Modal Component turbo_frame_tag で囲む Modal表⽰のerb (TurboFrame)
app/views/application/_remote_modal.html.erb ポイントはここ! 破⽚の中から、Stimulusの controllerを指定する この破⽚がブラウザに組み込まれたタイミングで 該当Stimulusのインスタンスが⽣成される →TurboFrameとStimulusを連携して、動きをつけられる Modal表⽰のerb (TurboFrame)
app/javascript/controllers/remote_modal_controller.js Modal表⽰のStimulus • `connect()`は、Stimulusのインス タンスが⽣成されたときに⾃動的に 起動するメソッド • TurboFrameで読み込んだHTMLに対 して、Stimulusで動きをつけられる •
`disconnect()`もある
これだけでモーダル表⽰できる 🎉
やること 1. TurboFrame + Stimulus でモーダルを開く 2. TurboStream で登録後の描画を切り替える 3.
ブラウザのURLを追随させる
やること 1. TurboFrame + Stimulus でモーダルを開く 2. TurboStream で登録後の描画を切り替える 3.
ブラウザのURLを追随させる
⼀般的な画⾯遷移による更新処理 編集フォームから更新すると
⼀般的な画⾯遷移による更新処理 エラーがあれば編集画⾯にとどまり
⼀般的な画⾯遷移による更新処理 更新に成功したら詳細画⾯にリダイレクトする
⼀般的な画⾯遷移による更新処理 更新に成功したら詳細画⾯にリダイレクトする モーダルでも同等な動きを実現したい
モーダルでの更新処理 編集フォームから更新すると
モーダルでの更新処理 エラーがあればモーダル上で表示され
モーダルでの更新処理 更新後に詳細画⾯が表⽰される
Controller#update app/controllers/products_controller.rb
Controller#update • 更新に成功しても、redirectしない • update.turbo_stream.erbがレンダリ ング対象 • 本来redirectするパス (product_path) を@turbo_pathにセット
→これは後述にて説明 app/controllers/products_controller.rb
Controller#update invalidの場合は :edit を再度レンダリン グする →これは通常の画⾯遷移時と同様 app/controllers/products_controller.rb
Turbo Stream app/views/products/update.turbo_stream.erb
Turbo Stream remote_modal の部分を @product で `replace` する (モーダルの内容が詳細画⾯に変わる) app/views/products/update.turbo_stream.erb
Turbo Stream app/views/products/update.turbo_stream.erb ⼀覧(index) に表⽰されているレコードの内容も 最新化する
以上で登録後の遷移ができる
やること 1. TurboFrame + Stimulus でモーダルを開く 2. TurboStream で登録後の描画を切り替える 3.
ブラウザのURLを追随させる
やること 1. TurboFrame + Stimulus でモーダルを開く 2. TurboStream で登録後の描画を切り替える 3.
ブラウザのURLを追随させる
管理画⾯の運⽤でよくあるシーン URLを使ってやり取りすることが多々ある 例えばSlackで...
管理画⾯の運⽤でよくあるシーン URLを使ってやり取りすることが多々ある 例えばSlackで... こんな感じで該当ページのURLを使って コミュニケーションしたい
単にModal化しただけでは ブラウザのURLが追随しない →URLを使った運⽤ができない 管理画⾯の実運⽤も考慮して 対処したい
2つの対策を提案 a) モーダル起動の link_to に `turbo_action: :advance` を指定 b) JavaScriptの
History API を使って制御する
2つの対策を提案 a) モーダル起動の link_to に `turbo_action: :advance` を指定 ∙ Railsの仕組みでできるのでシンプル
∙ Modalを閉じたときや、更新後の表⽰切り替え時に追随しない b) JavaScriptの History API を使って制御する ∙ URLのために仕組みを実装する必要 ∙ Modalを閉じたとき、更新後の表⽰切り替えも追随できる
2つの対策を提案 a) モーダル起動の link_to に `turbo_action: :advance` を指定 ∙ Railsの仕組みでできるのでシンプル
∙ Modalを閉じたときや、更新後の表⽰切り替え時に追随しない b) JavaScriptの History API を使って制御する ∙ URLのために仕組みを実装する必要 ∙ Modalを閉じたとき、更新後の表⽰切り替えも追随できる 今回はこちらの内容を説明
以下2つのURLを使う • Modalを表⽰したときのURL ◦ TurboFrameによるGETリクエスト or リダイレクトのURL ◦ Modalを開く際に、HistoryAPIにセットする •
Modalを閉じたときのURL ◦ Modalを開く直前のURLを location.href から取得しておく ◦ Modalのhideイベントをフックして、このURLに戻す
app/controllers/application_controller.rb ApplicationControllerの before_action で、turboでリクエスト されたURLを @turbo_path へセットし ておく Modal起動時のURL GETリクエストでModalを起動する
app/controllers/products_controller.rb 例えば #update に成功すると、通常の画⾯遷移版 では show_path へリダイレクトする。 そのpathを @turbo_path としてセットしておく。
Modal起動時のURL Modalにリダイレクトの動きをさせたい場合
app/views/application/_remote_modal.html.erb @turbo_path をModalに付与しておき、Stimulusを介 してHistoyAPIにセットする 前項で説明した turbo_frame でModal表示をするerb
app/javascript/controllers/remote_modal_controller.js 前述で説明した、Stimulusのconnect()を使って Modalを開くロジック部分 Modalを起動するStimulus
Modalを開く前に、URLの仕組みを ⼊れる app/javascript/controllers/remote_modal_controller.js Modalを起動するStimulus
app/javascript/controllers/remote_modal_controller.js Modalを起動するStimulus 前述の `turboPath` を HistoryAPIにセットするこ とで、Modal起動時にURLを追随させる
現在のパス=Modalを開く直前のパ ス (`location.href`) を、Modal#hide イベントをフックしてセットする app/javascript/controllers/remote_modal_controller.js Modalを起動するStimulus
以上でブラウザ上のURLが追随します
ちなみに、この状態で URLを直接指定したリクエストをすると...
特に何も仕組みを設けなくても表⽰できる
コード補足 a) 登録フォームのModalは、背景クリックでも閉じないように • ⼊⼒途中にうっかりModalが閉じることを防ぐ • 詳細ページなら背景クリックで閉じたほうが便利 b) Flashによるメッセージ表⽰ •
Turboだと少し仕組みを設ける必要 サンプルのGitHubリポジトリで実装しています github.com/yamataka22/kaigionrails2023-admin-modal
まとめ • Hotwireを使って、管理画⾯をModalでプチSPA化するポイントを説明 しました ◦ TurboFrameとStimulus (connect()) を連携させて、HTMLの破⽚に動き をつける ◦
TurboStreamで、Modal上の描画を切り替える(リダイレクトのイメー ジ) • 今回説明した内容は、管理画⾯はもちろん、⼀般的なフロント向け ページでも応⽤可能です
ご清聴ありがとうございました ※ご不明な点などあれば、お気軽にご連絡ください github.com/yamataka22