【问题标题】:Render fields based on category select rails基于类别选择栏呈现字段
【发布时间】:2020-10-07 22:51:25
【问题描述】:

所以我有以下表格,使用茧嵌套部分字段

<%= form_with(model: tournament, local: true, class: "mt-8 md:mt-12") do |f| %>
  <% if tournament.errors.any? %>
    <div id="error_explanation" class="bg-red-100 text-red-700 rounded-md shadow-sm p-8">
      <h2 class="font-bold text-base"><%= pluralize(tournament.errors.count, "error") %> prohibited this tournament from being saved:</h2>

      <ul>
        <% tournament.errors.full_messages.each do |message| %>
          <li class="mt-1 font-semibold text-sm"><%= message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  ....

  <div class="text-xl font-black mt-8">
    Tournament Standings
    <div class="border-2 border-indigo-600 bg-indigo-600 w-1/6 md:w-10 mt-1"></div>
  </div>

  <%= f.fields_for :tournament_standings do |tournament_standing| %>
    <%= render 'tournament_standing_fields', f: tournament_standing %>
  <% end %>

  <div class="mt-4 border-t border-gray-200 pt-5">
    <span class="mt-4 inline-flex rounded-md shadow-sm">
      <%= f.submit class: "mr-4 inline-flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:border-indigo-700 focus:shadow-outline-indigo active:bg-indigo-700 transition duration-150 ease-in-out" %>
      <%= link_to_add_association 'Add tournament standings', f, :tournament_standings, class: "inline-flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:border-indigo-700 focus:shadow-outline-indigo active:bg-indigo-700 transition duration-150 ease-in-out mr-2" %>
    </span>
  </div>
<% end %>

在该渲染中,我有以下内容

<div class="mt-4">
  <%= f.label "Select tournament game", class: "block text-sm font-medium text-gray-700" %>
  <div class="mt-1 rounded-md shadow-sm">
    <%= f.select(:category_id, Category.all.map{|c| [c.name, c.id]}, {prompt: true}, { class: "ts_select block form-select w-full transition duration-150 ease-in-out sm:text-sm sm" }) %>
  </div>
</div>

<div class="nested-fields">
  <div class="mt-4">
    <%= f.label :team, class: "block text-sm font-medium text-gray-700" %>
    <div class="mt-1 rounded-md shadow-sm">
      <%= f.select(:team_id, Team.all.map{|t| [t.name, t.id]}, {prompt: "Select a team"}, { class: "block form-select w-full transition duration-150 ease-in-out sm:text-sm" }) %>
    </div>
  </div>

  <div class="flex flex-col md:flex-row">
    <div class="mt-4 md:mr-4">
      <div class="mt-1">
        <div class="flex rounded-md shadow-sm">
          <span class="inline-flex items-center px-3 rounded-l-md border border-r-0 border-gray-300 bg-gray-50 text-gray-500 sm:text-sm">
            Position
          </span>
          <%= f.number_field :position, class: "flex-1 form-input block w-full rounded-none rounded-r-md transition duration-150 ease-in-out sm:text-sm sm" %>
        </div>
      </div>
    </div>

    <%= render partial: "tournaments/fpartials/default", tournament: @tournament, locals: { f: f } %>
    <%= render partial: "tournaments/fpartials/rocket_league_fields", tournament: @tournament, locals: { f: f } %>

    <div class="mt-4 md:mr-4">
      <div class="mt-1">
        <div class="flex rounded-md shadow-sm">
          <span class="inline-flex items-center px-3 rounded-l-md border border-r-0 border-gray-300 bg-gray-50 text-gray-500 sm:text-sm">
            Assists
          </span>
          <%= f.number_field :assists, class: "flex-1 form-input block w-full rounded-none rounded-r-md transition duration-150 ease-in-out sm:text-sm sm" %>
        </div>
      </div>
    </div>

    <div class="mt-4">
      <div class="mt-1">
        <div class="flex rounded-md shadow-sm">
          <span class="inline-flex items-center px-3 rounded-l-md border border-r-0 border-gray-300 bg-gray-50 text-gray-500 sm:text-sm">
            Prize $
          </span>
          <%= f.number_field :prize, class: "flex-1 form-input block w-full rounded-none rounded-r-md transition duration-150 ease-in-out sm:text-sm sm" %>
        </div>
      </div>
    </div>
  </div>

  <%= link_to_remove_association 'Delete tournament standing', f, class: "mt-4 inline-flex justify-center text-sm font-medium" %>
</div>

哪个工作,如您所见,我有两个渲染部分,我希望能够根据所选类别显示这些字段category_id 默认应该是默认显示的字段和隐藏的火箭联盟字段,但是,让我们假设用户选择了rocket league的类别,那么默认字段需要隐藏,火箭联盟字段显示。

对此的任何帮助都会很好地让它在局部范围内工作。

【问题讨论】:

  • 澄清一下:您是否希望在用户更改类别选择或用户更改选择并提交表单(即单击按钮)时动态更改显示?您可以轻松地根据值有条件地渲染您的部分,但如果您想要动态切换,则需要一些 Javascript 将其粘合在一起。
  • 动态切换@rmlockerd

标签: jquery ruby-on-rails ruby cocoon-gem


【解决方案1】:

有两种方法:

  1. 在页面加载时呈现所有部分,并在选择框更改时使用 Javascript 显示/隐藏相应的部分。
  2. 使用 AJAX 请求呈现正确的部分,然后使用 Javascript 将其动态放入页面/DOM。

如果您有大量可能的部分或它们非常大,则选项 2 更可取。但是,如果您只是在谈论在两件事之间切换,则选项 1 更直接。

对于选项 1:

  1. 使用不同的 ID 将您的部分包装在 &lt;div&gt;s 中,以便您的 Javascript 可以访问它们。在上面的代码中,您似乎最初并未在选择框上设置值,因此您可能会从显示的“默认”设置开始:

    <div id="default-fields">
      <%= render partial: "tournaments/fpartials/default", tournament: @tournament, locals: { f: f } %>
    </div>
    <div id="rocket-fields" hidden>
      <%= render partial: "tournaments/fpartials/rocket_league_fields", tournament: @tournament, locals: { f: f } %>
    </div>
    

    (当然,您也可以在渲染时有条件地设置“隐藏”。)

  2. 添加一个 Javascript 处理程序,该处理程序在所选值更改时触发。 “不显眼”的方法是在页面的 Javascript 包中添加一个 Javascript 事件侦听器(通常在 app/assets/javascript 中)。比如:

    document.addEventListener('turbolinks:load', () => {
      const element = document.getElementById('tournament[category_id]');
      if (element) {
        $('#tournament[category_id]').change((e) => {
          if (e.target.value == 'whatever_rocket_id_is') {
            ('#default-fields').hide();
            ('#rocket-fields').show();
          }
          else {
            ('#default-fields').show();
            ('#rocket-fields').hide();
          }
        });
      }
    });
    

注意:因为您希望类别和显示的字段之间具有紧密耦合,所以您不应该使用记录 ID 作为选择选项中的键;它可以改变,你不想在你的 Javascript 中硬编码记录 ID。您最好的选择可能是对键和值都使用类别名称。首先可能还值得重新考虑这种紧密耦合。

【讨论】:

    猜你喜欢
    • 2021-11-23
    • 2016-04-13
    • 2015-02-02
    • 1970-01-01
    • 2014-08-09
    • 1970-01-01
    • 2017-06-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多