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

时间:2010-06-12 01:38:24

标签: ruby-on-rails ruby form-submit

我需要有多个提交按钮。

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

一个按钮可以正常创建。

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

我该怎么做?我无法改变路线,所以有没有办法发送一个由[:params]拾取的另一个变量?

如果我这样做,我在控制器中做什么,设置一个案例陈述?

7 个答案:

答案 0 :(得分:122)

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

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

这将输出:

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

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

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

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

答案 1 :(得分:58)

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

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

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

  

formaction:
  处理输入元素提交的信息的程序的URI(如果它是提交按钮或图像)。如果已指定,则会覆盖元素的表单所有者的操作属性。   资料来源:MDN

答案 2 :(得分:29)

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

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

有点不舒服,因为你必须检查params键存在而不是简单地检查params[:commit]值:你会收到params[:a_button]params[:b_button],具体取决于按下了哪一个。< / p>

答案 3 :(得分:12)

与@ 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

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

答案 4 :(得分:9)

我们在rails中使用advanced constraints解决了。

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

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

CommitParamRouting是一个简单的类,它有一个方法matches?,如果commit参数匹配给定的实例attr,则返回true。值。

这可用作宝石commit_param_matching

答案 5 :(得分:3)

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

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

然后在视图中:

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

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

答案 6 :(得分:1)

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