Ruby-on-rails 如何在 Rails 中为同一个表单创建多个提交按钮?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3027149/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 22:46:27  来源:igfitidea点击:

How do I create multiple submit buttons for the same form in Rails?

ruby-on-railsrubyform-submit

提问by Timothy T.

I need to have multiple submit buttons.

我需要有多个提交按钮。

I have a form which creates an instance of Contact_Call.

我有一个创建 Contact_Call 实例的表单。

One button creates it as normal.

一键即可正常创建。

The other button creates it but needs to have a different :attribute value from the default, and it also needs to set the attribute on a different, but related model used in the controller.

另一个按钮创建它,但需要有一个与默认值不同的 :attribute 值,它还需要在控制器中使用的不同但相关的模型上设置属性。

How do I do that? I can't change the route, so is there a way to send a different variable that gets picked up by [:params]?

我怎么做?我无法更改路线,那么有没有办法发送一个由 [:params] 获取的不同变量?

And if I do then, what do I do in the controller, set up a case statement?

如果我这样做了,我在控制器中做什么,设置一个 case 语句?

回答by Anurag

You can create multiple submit buttons and provide a different value to each:

您可以创建多个提交按钮并为每个按钮提供不同的值:

<% form_for(something) do |f| %>
    ..
    <%= f.submit 'A' %>
    <%= f.submit 'B' %>
    ..
<% end %>

This will output:

这将输出:

<input type="submit" value="A" id=".." name="commit" />
<input type="submit" value="B" id=".." name="commit" />

Inside your controller, the submitted button's value will be identified by the parameter commit. Check the value to do the required processing:

在您的控制器中,提交按钮的值将由参数 标识commit。检查值以进行所需的处理:

def <controller action>
    if params[:commit] == 'A'
        # A was pressed 
    elsif params[:commit] == 'B'
        # B was pressed
    end
end

However, remember that this tightly couples your view to the controller which may not be very desirable.

但是,请记住,这将您的视图与控制器紧密耦合,这可能不是很理想。

回答by patpir

There is also another approach, using the formaction attribute on the submit button:

还有另一种方法,使用提交按钮上的 formaction 属性:

<% form_for(something) do |f| %>
    ...
    <%= f.submit "Create" %>
    <%= f.submit "Special Action", formaction: special_action_path %>
<% end %>

The code stays clean, as the standard create button doesn't need any change, you only insert a routing path for the special button:

代码保持干净,因为标准的创建按钮不需要任何更改,您只需为特殊按钮插入路由路径:

formaction:
The URI of a program that processes the information submitted by the input element, if it is a submit button or image. If specified, it overrides the action attribute of the element's form owner. Source: MDN

formaction:
处理输入元素提交的信息的程序的 URI,如果它是提交按钮或图像。如果指定,它将覆盖元素表单 owner 的 action 属性。来源:MDN

回答by masciugo

You can alternatively recognized which button was pressed changing its attribute name.

您也可以通过更改其属性名称来识别按下了哪个按钮。

<% form_for(something) do |f| %>
    ..
    <%= f.submit 'A', name: 'a_button' %>
    <%= f.submit 'B', name: 'b_button' %>
    ..
<% end %>

It's a little bit uncomfortable because you have to check for params keys presence instead of simply check params[:commit]value: you will receive params[:a_button]or params[:b_button]depending on which one was pressed.

这有点不舒服,因为您必须检查 params 键是否存在,而不是简单地检查params[:commit]值:您将收到params[:a_button]params[:b_button]取决于按下了哪个键。

回答by Tadas Sasnauskas

Similar solution to one suggested by @vss123 without using any gems:

与@vss123 建议的类似解决方案,不使用任何宝石:

resources :plan do
  post :save, constraints: lambda {|req| req.params.key?(:propose)}, action: :propose
  post :save, constraints: lambda {|req| req.params.key?(:finalize)}, action: :finalize
end

Notice that I avoid using value and use input name instead since submit button value is often internationalized / translated. Also, I'd avoid using this too much since it will quickly clutter your routes file.

请注意,我避免使用值并使用输入名称,因为提交按钮值通常是国际化/翻译的。另外,我会避免过多使用它,因为它会很快弄乱您的路由文件。

回答by siliconsenthil

We solved using advanced constraintsin rails.

我们解决了在 rails 中使用高级约束的问题。

The idea is to have the same path (and hence the same named route & action) but with constraints routing to different actions.

这个想法是具有相同的路径(因此具有相同的命名路由和操作),但具有路由到不同操作的约束。

resources :plan do
  post :save, constraints: CommitParamRouting.new("Propose"), action: :propose
  post :save, constraints: CommitParamRouting.new("Finalize"), action: :finalize
end

CommitParamRoutingis a simple class that has a method matches?which returns true if the commit param matches the given instance attr. value.

CommitParamRouting是一个简单的类,它有一个方法matches?,如果提交参数与给定的实例属性匹配,则返回 true。价值。

This available as a gem commit_param_matching.

这可作为 gem commit_param_matching 使用

回答by Draknor

An old question, but since I've been dealing with the same situation, I thought I'd post my solution. I'm using controller constants to avoid introducing a discrepancy between the controller logic and the view button.

一个老问题,但由于我一直在处理同样的情况,我想我会发布我的解决方案。我使用控制器常量来避免在控制器逻辑和视图按钮之间引入差异。

class SearchController < ApplicationController
  SEARCH_TYPES = {
    :searchABC => "Search ABCs",
    :search123 => "Search 123s"
  }

  def search
    [...]
    if params[:commit] == SEARCH_TYPES[:searchABC]
      [...]
    elsif params[:commit] == SEARCH_TYPES[:search123]
      [...]
    else
      flash[:error] = "Search type not found!"]
      [...]
    end
  end
  [...]          
end

And then in the view:

然后在视图中:

<% form_for(something) do |f| %>
    [...]
    <%= f.submit SearchController::SEARCH_TYPES[:searchABC] %>
    <%= f.submit SearchController::SEARCH_TYPES[:search123] %>
    [...]
<% end %>

This way the text only lives in one place - as a constant in the controller. I haven't tried to figure out how to i18n this yet, however.

这样文本只存在于一个地方——作为控制器中的一个常量。然而,我还没有试图弄清楚如何实现这一点。

回答by Shawn Walton

I have a variable number of submit buttons on my form thanks to nested_form_fields, so just using the name wasn't enough for me. I ended up including a hidden input field in the form and using Javascript to populate it when one of the form submit buttons was pressed.

由于nested_form_fields,我的表单上有可变数量的提交按钮,所以仅使用名称对我来说是不够的。我最终在表单中包含了一个隐藏的输入字段,并在按下表单提交按钮之一时使用 Javascript 来填充它。