Rails: リソースの一括登録画面: 7: 削除ボタンの表示変更

前回の続きです。子要素(登録グループ)が1つの場合は削除ボタンを非表示にします。

Stimulusのコントローラーを作成します。

bin/rails generate stimulus only-child-hidden

app/javascript/controllers/only_child_hidden_controller.js
子要素(childList)が1つの場合に対象の要素(element)を非表示にします。
data-controller="only-child-hidden"
data-only-child-hidden-target="childList"
data-only-child-hidden-target="element"

import { Controller } from "@hotwired/stimulus"

// Connects to data-controller="only-child-hidden"
export default class extends Controller {
  static targets = [ "childList", "hiddenElement" ]

  // 初期表示時、エラー表示時
  connect() {
    this.hideElements(this.isHidden(this.childListTarget.childElementCount))
    const observer = new MutationObserver(mutations => this.childListChanged(mutations))
    observer.observe(this.childListTarget, {childList: true, subtree: false})
  }

  isHidden(childElementCount) {
    return childElementCount <= 1
  }

  hideElements(hidden) {
    this.hiddenElementTargets.forEach(item => item.hidden = hidden)
  }

  // 子要素追加削除時
  childListChanged(mutations) {
    this.hideElements(this.isHidden(mutations[0].target.childElementCount))
  }
}

app/views/bulk_accounts/new.html.erb
only-child-hiddenコントローラーを指定します。
data: { controller: "only-child-hidden" }

<div class="mx-auto md:w-2/3 w-full">
  <% if notice.present? %>
    <p class="py-2 px-3 bg-green-50 mb-5 text-green-500 font-medium rounded-lg inline-block" id="notice"><%= notice %></p>
  <% end %>
  <% if alert.present? %>
    <p class="py-2 px-3 bg-red-50 mb-5 text-red-500 font-medium rounded-lg inline-block" id="alert"><%= alert %></p>
  <% end %>

  <h1 class="font-bold text-4xl">New accounts</h1>

  <%= form_with(url: :bulk_accounts, data: { controller: "only-child-hidden" }) do |form| %>
    <div id="accounts" data-only-child-hidden-target="childList">
      <%= render partial: "account", collection: @accounts %>
    </div>
    <div class="mb-20">
      <%= link_to "Add account", bulk_accounts_group_path, data: { turbo_method: :post } %>
    </div>
    <div>
      <%= form.submit class: "rounded-lg py-3 px-5 bg-blue-600 text-white inline-block font-medium cursor-pointer" %>
    </div>
  <% end %>
</div>

app/views/bulk_accounts/_account.html.erb
hiddenElementターゲットを指定します。
data-only-child-hidden-target="hiddenElement"

<%= tag.div data: { controller: "element-removal" }, class: "py-2 px-3 mb-5" do %>
  <a hidden data-action="element-removal#remove" data-only-child-hidden-target="hiddenElement">Remove</a>
  <%= fields_for "accounts[]", account do |account_fields| %>
    <%= render "bulk_accounts/account_text_field", account: account, account_fields: account_fields, key: :name %>
    <%= render "bulk_accounts/account_text_field", account: account, account_fields: account_fields, key: :email %>
  <% end %>
<% end %>

課題

アイコンボタンに変更する。

コントローラーの責務と名前がしっくり来ていませんがこのままにします。凝集度の高いコントローラーを作り、こちらの投稿で紹介されている方法で連携させるのも良いのかもしれません。

以上です。

続きを書きました。

この記事が気に入ったらサポートをしてみませんか?