Ruby on rails 如何在rails中实现嵌套下拉列表

Ruby on rails 如何在rails中实现嵌套下拉列表,ruby-on-rails,select,dropdown,Ruby On Rails,Select,Dropdown,我想实现基于模型的下拉列表,当一个下拉列表模型的值被选中时,它将作为第二个下拉列表中选择的基础 <div class="study-search"> <%= form_with(url: show_subjects_path(:site_id), method: :get, html: {style: 'font-size:16px'}) do |f| %> <%= f.label 'Select Study' %> &

我想实现基于模型的下拉列表,当一个下拉列表模型的值被选中时,它将作为第二个下拉列表中选择的基础

<div class="study-search">
  <%= form_with(url: show_subjects_path(:site_id), method: :get, html: {style: 'font-size:16px'}) do |f| %>
    <%= f.label 'Select Study' %>
    <%= f.select :id, Study.all.collect {|study| [study.title, study.id] },  {:include_blank => "--Choose--"}%>
    <%= f.label 'Select Site' %>
    <%= f.select :site_id, Site.where(study_id: :id).collect {|site| [site.name, site.id] },  {:include_blank => "--Choose--"}%>
    <div class="btn btn-sm", style="display: inline">
      <%= f.submit "GO" %>
    </div>
  <% end %>
</div>
因此,我要求使用第一个下拉列表中的id为第二个下拉列表应用过滤器

<div class="study-search">
  <%= form_with(url: show_subjects_path(:site_id), method: :get, html: {style: 'font-size:16px'}) do |f| %>
    <%= f.label 'Select Study' %>
    <%= f.select :id, Study.all.collect {|study| [study.title, study.id] },  {:include_blank => "--Choose--"}%>
    <%= f.label 'Select Site' %>
    <%= f.select :site_id, Site.where(study_id: :id).collect {|site| [site.name, site.id] },  {:include_blank => "--Choose--"}%>
    <div class="btn btn-sm", style="display: inline">
      <%= f.submit "GO" %>
    </div>
  <% end %>
</div>
以下代码段中使用的:id的方式不正确。请建议正确的方法

<%= f.select :site_id, Site.where(study_id: :id).collect {|site| [site.name, site.id] },  {:include_blank => "--Choose--"}%>

解决这个问题的方法有多种,但复杂程度不同。我将从最简单但可能笨重的开始,到最复杂的

前两个选项将进行完整的页面刷新,这并不像听起来那么糟糕,特别是如果您使用的是以前称为TurboLink的Turbo Drive

这两个选项的警告是,导航将始终是一个Turbo-visit导航,这意味着每次您都将在导航堆栈中创建一个新页面。您可以通过使用stimultive覆盖表单提交并使用replace操作发出turboget请求来克服这一问题。有关这方面的更多信息,请参阅

选项1:最简单的一个 如果用户在更改第一个选择框时按下Go按钮,您所拥有的已经可以实现您的期望。您只需将Site select更改为按表单发送的参数进行筛选:

    <%= f.select :site_id, Site.where(study_id: params[:site_id]).collect {|site| [site.name, site.id] },  {:include_blank => "--Choose--"}%>

将你的刺激控制器添加到表单中。 注意,controller和action关键字被添加到表单_with method和第一个f.select方法中

这将基本上模拟用户在第一次选择更改时单击Go按钮

选项3:使用涡轮车架 如果您使用的是最新版本的rails,并且包含了hotwire rails gem,那么您将能够利用rails的所有新技术以及随之而来的HTML over the wire技术

最新版本的turbo现在处理表单,而不是Turbolinks。有关如何执行此操作的技术,请参阅。对于turbo帧,您的操作与选项1和选项2基本相同,选项1和选项2发送GET请求并返回完整页面作为响应,但区别在于,对于turbo帧,您可以有选择地替换部分DOM

我还不是一个涡轮帧专家,所以我不会发布一个确切的例子

选项4:使用涡轮流 这是最复杂的选项,但就使用Action Cable设置环境而言,仍然相对简单。turbostream所做的是允许您使用5个基本的DOM操作:追加、前置、替换、更新和删除,以更新DOM为目标。这些操作将使用web套接字连接从服务器流回到前端

在您的情况下,您可能希望用新的选项列表替换或更新select

我还不是涡轮流方面的专家,所以我不会发布一个确切的例子

选项5:退房 从StimulusReflex的网站:

[Stimulus Reflection]是一种利用Ruby on Rails构建现代、反应式web界面的新方法。 我们通过拦截用户交互并通过实时WebSocket将其传递给Rails,扩展了Rails和Stimulus的功能。这些交互由改变应用程序状态的反射动作处理。将快速重新呈现当前页面,并使用CableReady将更改发送到客户端。然后修改页面以反映新的应用程序状态。整个往返过程允许我们在20-30毫秒内更新UI,而不会出现闪烁或昂贵的页面加载

通过刺激反射,你可以获得一个无缝的体验来完成这些类型的交互页面,但它需要额外的依赖性。这绝对值得一试,但它也是一个新的依赖项,假设您采用了版本7中的新Rails默认值(其中包括Hotwire),您将在代码库中引入它

选项6:100%前端 使用Stimulus JS,当页面仅使用javascript加载和过滤时,您可以从所有站点加载所有选项。这是可行的,但它肯定更复杂,因为您需要编写更多的javascript,如果您有太多的站点可供搜索,那么初始页面加载可能会很慢。我不推荐这种方法,因为它可能会给你的应用程序增加不必要的复杂性,但这是一种选择

最后的想法 不管您做什么,如果您希望在用户更改前端某些内容时提交表单,例如更改选择字段的值或在文本字段中键入内容,或悬停或任何其他可在前端跟踪的操作,则需要编写一点javascript。我强烈建议您查看StimulusJS,它是Hotwire的一部分,Hotwire是rails生态系统前端的最新添加,它将是在即将发布的rails 7版本中构建应用程序的默认方式

我希望这能给你一些启示

一些额外的链接,以赶上所有的东西热线刺激,涡轮等 GoRails在这个主题上有很棒的资源

你在干什么
求爱是一种幸福。Dropdown是一个模糊的术语,用于表示可以由任何类型的element.PS构建的UI模式。snippets函数用于可在浏览器中运行的CSS/JS/HTML代码示例。不要将其用于任意服务器端代码。