微炭酸ログ

Ruby や Rails を中心に。

Turbo Frames を学ぶ

前提

  • Rails で、turbo-rails を使用しています。

最も基本的な動き

編集ボタンを押すと、turbo_frame_tag 'edit_room' の部分が、edit.html.hamlturbo_frame_tag 'edit_room' の部分で置き換わります。

f:id:tsubasa-yoshida:20210531203157g:plain

↓app/views/rooms/show.html.haml

= turbo_frame_tag 'edit_room' do
  .d-flex
    %h1.rooms-index-title.mb-0= @room.name
    .ms-auto
      = link_to '編集', edit_room_path(@room), class: 'btn btn-outline-primary'
      -# わざわざここにルーム一覧ボタンを置く意味はないが、今回は data: { turbo_frame: :_top } の動きを確認するために置く
      = link_to 'ルーム一覧', rooms_path, class: 'btn btn-outline-secondary', data: { turbo_frame: :_top }

.mt-3
  = turbo_frame_tag 'new_message', src: new_room_message_path(@room), target: :_top

#messages.mt-3
  = render @room.messages.recently_posted_order

↓app/views/rooms/edit.html.haml

= turbo_frame_tag 'edit_room' do
  = form_with model: @room, class: 'd-flex' do |f|
    .flex-grow-1.me-2
      = f.text_field :name, class: 'form-control'
    = f.submit '更新する', class: 'btn btn-primary me-2'
    = link_to 'キャンセル', :back, class: 'btn btn-outline-secondary', data: { turbo_frame: :_top }

= button_to 'ルームを削除する', room_path(@room), method: :delete,
    data: { confirm: '本当によろしいですか?' }, class: 'btn btn-outline-danger mt-3'

data: { turbo_frame: :_top } の動き

data: { turbo_frame: :_top } をつけると、差し込みではなく、従来のリンクと同じ動きになります。

↓app/views/rooms/show.html.haml

= turbo_frame_tag 'edit_room' do
  .d-flex
    %h1.rooms-index-title.mb-0= @room.name
    .ms-auto
      = link_to '編集', edit_room_path(@room), class: 'btn btn-outline-primary'
      -# わざわざここにルーム一覧ボタンを置く意味はないが、今回は data: { turbo_frame: :_top } の動きを確認するために置く
      = link_to 'ルーム一覧', rooms_path, class: 'btn btn-outline-secondary', data: { turbo_frame: :_top }

target: :_top の動き

target: :_top をつけると、turbo_frame_tag で囲っている中のリンクやフォームが、従来の動きと同じになります。
data: { turbo_frame: :_top } と似ていますが、囲っている要素につけるか、囲い自体につけるかで使い分ける感じです。

↓app/views/messages/new.html.haml

%h1 メッセージ作成

= turbo_frame_tag 'new_message', target: :_top do
  = form_with model: [@room, @message] do |f|
    = f.text_area :content, rows: 4, class: 'form-control'
    .text-end.mt-2
      = f.submit '作成する', class: 'btn btn-primary'

src 属性の動き

turbo_frame_tag に src 属性をつけると、その値のURLに非同期通信が走り、
ページ描画時に new.html.hamlturbo_frame_tag 'new_message' の部分で置き換わります。

↓app/views/rooms/show.html.haml

.mt-3
  = turbo_frame_tag 'new_message', src: new_room_message_path(@room), target: :_top

↓app/views/messages/new.html.haml

%h1 メッセージ作成

= turbo_frame_tag 'new_message', target: :_top do
  = form_with model: [@room, @message] do |f|
    = f.text_area :content, rows: 4, class: 'form-control'
    .text-end.mt-2
      = f.submit '作成する', class: 'btn btn-primary'

loading="lazy" の動き

未検証ですが、loading="lazy" をつけると、そのDOMが画面に表示されるまで読み込みを遅延させるようです。
縦に長いページなどで有効かもしれません。

↓app/views/rooms/show.html.haml

.mt-3
  = turbo_frame_tag 'new_message', src: new_room_message_path(@room), target: :_top, loading: :lazy

疑問点や今後確認すること

  • 1度更新すると、show の編集ボタンが押せなくなる
  • edit で更新すると、当然だけどフレームが置き換わってしまう
  • キャンセルボタンはどう実装すべきか
    • edit にはそもそも出したくない件
    • そもそもやりたい動き:切り替えたフレームを元に戻したい
  • メッセージ投稿を非同期通信にしたい
  • バリデーションどうなる?

参考