我需要有多个提交按钮。
我有一个表单,它创建了 Contact_Call 的一个实例。
一个按钮按照正常方式创建该实例。
另一个按钮创建它,但需要具有不同的 :attribute 值,它还需要在控制器中使用的另一个相关模型上设置属性。
如何做到这一点?我不能更改路由,那么是否有一种方法可以发送不同的变量,然后被[:params]捕获?
如果我这样做,那么在控制器中我该怎么办,设置一个 case 语句吗?
我需要有多个提交按钮。
我有一个表单,它创建了 Contact_Call 的一个实例。
一个按钮按照正常方式创建该实例。
另一个按钮创建它,但需要具有不同的 :attribute 值,它还需要在控制器中使用的另一个相关模型上设置属性。
如何做到这一点?我不能更改路由,那么是否有一种方法可以发送不同的变量,然后被[:params]捕获?
如果我这样做,那么在控制器中我该怎么办,设置一个 case 语句吗?
您可以创建多个提交按钮,并为每个按钮提供不同的值:
<% 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
然而,请记住,这会严密地将您的视图与控制器耦合在一起,这可能并不是非常理想的。
还有另一种方法,使用submit按钮上的formaction属性:
<% form_for(something) do |f| %>
...
<%= f.submit "Create" %>
<%= f.submit "Special Action", formaction: special_action_path %>
<% end %>
标准的创建按钮不需要任何更改,代码保持清洁,你只需为特殊按钮插入一个路由路径:
formaction:
如果是提交按钮或图像,则该输入元素提交的信息将由指定的程序处理的 URI。如果指定了 formaction 属性,则覆盖元素的表单所有者的 action 属性。 来源:MDN
<%= hidden_field_tag :authenticity_token, form_authenticity_token %>
。 - irruputuncu您可以通过更改按钮的属性名称来识别哪个按钮被按下。
<% form_for(something) do |f| %>
..
<%= f.submit 'A', name: 'a_button' %>
<%= f.submit 'B', name: 'b_button' %>
..
<% end %>
这有点不舒服,因为你必须检查参数键是否存在,而不是仅仅检查params[:commit]
值:你将收到params[:a_button]
或params[:b_button]
,具体取决于哪个按钮被按下。
与@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
请注意,我避免使用value并使用input name,因为提交按钮的值经常需要国际化/翻译。此外,我会避免过多地使用它,因为它会很快使您的路由文件混乱。
我们使用Rails中的高级约束来解决问题。
这个想法是使用相同的路径(因此具有相同的命名路由和操作),但是通过约束条件将其路由到不同的操作。
resources :plan do
post :save, constraints: CommitParamRouting.new("Propose"), action: :propose
post :save, constraints: CommitParamRouting.new("Finalize"), action: :finalize
end
CommitParamRouting
是一个简单的类,具有一个方法 matches?
,如果提交参数与给定的实例属性值匹配,则返回 true。
这作为 gem 可在 commit_param_routing 中找到。
这是一个老问题,但由于我也遇到了同样的情况,所以我想发布我的解决方案。我使用控制器常量来避免引入控制器逻辑和视图按钮之间的差异。
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 %>
这样,文本只存在于控制器中的一个常量中。我还没有尝试想出如何进行国际化处理。
由于使用了nested_form_fields,我的表单上有可变数量的提交按钮,因此仅使用名称是不够的。最终我在表单中包含了一个隐藏的输入字段,并在表单提交按钮之一被按下时使用JavaScript来填充它。