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
710
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
RaaP
ksss
0
150
Adding Security to Microcontroller Ruby
sylph01
1
150
TSKaigi 2024 - 新サービス Progate Path の演習で TypeScript を採用して見えた教材観点からの利点と課題
makotoshimazu
1
220
Node.js v22 で変わること
yosuke_furukawa
PRO
12
4.2k
ServerAction で Progressive Enhancement はどこまで頑張れるか? / progressive-enhancement-with-server-action
takefumiyoshii
6
510
一文字エイリアスのすすめ
fujimura
0
190
Docker_OSS_ホスティング入門
satokoki645
0
140
Revisiting the Hotwire Landscape after Turbo 8 @ RailsConf 2024, Detroit
marcoroth
3
610
slow types ってなんだろう?
karad
0
210
欠陥を早期に発見するための Software Engineer in Test とその重要性 / What is Software Engineer in Test and How they works
orgachem
PRO
17
2.3k
TypeScript 関数型スタイルでバックエンド開発のリアル
naoya
49
16k
Exploring the Implementation of “t.Run”, “t.Parallel”, and “t.Cleanup”
akarin
1
160
Featured
See All Featured
RailsConf 2023
tenderlove
9
580
Imperfection Machines: The Place of Print at Facebook
scottboms
261
12k
5 minutes of I Can Smell Your CMS
philhawksworth
199
19k
Faster Mobile Websites
deanohume
300
30k
What's in a price? How to price your products and services
michaelherold
238
11k
Creatively Recalculating Your Daily Design Routine
revolveconf
211
11k
A designer walks into a library…
pauljervisheath
201
23k
The World Runs on Bad Software
bkeepers
PRO
61
6.7k
Build your cross-platform service in a week with App Engine
jlugia
226
17k
Typedesign – Prime Four
hannesfritz
36
2.1k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
245
20k
The Cost Of JavaScript in 2023
addyosmani
21
4k
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