lynx   »   [go: up one dir, main page]

Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Rails: Turbo Framesで追加されるDOMノードをうまく扱う方法(翻訳)

概要

元サイトの許諾を得て翻訳・公開いたします。

日本語タイトルは内容に即したものにしました。

Rails: Turbo Framesで追加されるDOMノードをうまく扱う方法(翻訳)

私はReact方面の出身で、Reactとの付き合いも長いので、それ以来ずっとReactのファンです。
そんな私も最近Hotwireを使うようになって、たちまちHotwireに惚れ込んでしまいました。Hotwireのシンプルな方法論と効率の良さは印象的です。しかしHotwireと付き合ううちにいくつか面食らった点があります。

面食らった点の1つは、DOM内でのTurbo Framesの振る舞いです。
Reactなら、<Fragment>(またはショートハンドの<>)を使えばDOM構造に余計なノードが追加されることを簡単に回避できます。
しかし<turbo-frame>タグはDOM内に物理的に埋め込まれるため、表示やスタイルで思わぬ問題が発生することがあります。

最初はシンプルな例を考えてみましょう。

LPレコードのコレクションを表示するアプリで、LPレコードのリストを表示するときに、リストの最初の要素を「New Record」の追加ボタンにしたいとします。

基本的なマークアップは以下のとおりです。

  <ul class="grid grid-cols-4 gap-8">
    <li>
      <div class="w-full bg-black aspect-square">
        <%= link_to new_record_path, :class => "bg-blue-500 text-white px-2 py-1 rounded-md size-full flex items-center justify-center" do %>
          <span class="text-2xl text-center"><span class="text-4xl">+</span><br/> New Record</span>
        <% end %>
      </div>
    </li>
    <% @records.each do |record| %>
      <li class="relative">
        <%= link_to  record_path(record) do %>
          <div class="w-full bg-black aspect-square">
            <%= image_tag record.cover, class: "size-full object-contain" if record.cover.present? %>
          </div>
        <% end %>
      </li>
    <% end %>
  </ul>

上は以下のように表示されるはずです。

次に、これらのレコードを以下のようにTurbo Frameでラップして、「New Record」追加ボタン(new_record_path)はその外側に配置したいとします。

  <ul class="grid grid-cols-4 gap-8">
    <li>
      <div class="w-full bg-black aspect-square">
        <%= link_to  new_record_path, :class => "bg-blue-500 text-white px-2 py-1 rounded-md size-full flex items-center justify-center" do %>
          <span class="text-2xl text-center"><span class="text-4xl">+</span><br/> New Record</span>
        <% end %>
      </div>
    </li>
    <%= turbo_frame_tag "records" do %>
      <% @records.each do |record| %>
        <li class="relative">
          <%= link_to  record_path(record) do %>
            <div class="w-full bg-black aspect-square">
              <%= image_tag record.cover, class: "size-full object-contain" if record.cover.present? %>
            </div>
          <% end %>
        </li>
      <% end %>
    <% end %>
  </ul>

しかし結果は期待どおりになりませんでした。

🔗 何が問題か

Turbo Framesは新しい要素としてDOMに挿入されるため、レイアウトが崩れる可能性があります。フレームがgridの第2カラムに挿入されると、全レコードもそこに挿入されます。

🔗 修正方法

修正は可能です!解決方法の1つは、フレームをCSSで「透明」にするという昔ながらの方法です。必要な作業は、displayプロパティをcontentsに設定することだけです。

.your-turbo-frame {
  display: contents;
}

これでフレームが透明になり、LPレコードのリストが正しく表示されるようになりました。 🎉

関連記事

Railsを快適に開発するための最新フロントエンドツールキット(翻訳)

Rails: HotwireCombobox gemが素晴らしすぎるという話(翻訳)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。
Лучший частный хостинг