Как создать несколько кнопок отправки для одной и той же формы в Rails?
Мне нужно иметь несколько кнопок отправки.
У меня есть форма, которая создает экземпляр Contact_Call.
Одна кнопка создает его как обычно.
Другая кнопка создает его, но должна иметь другое значение атрибута по умолчанию, и ему также необходимо установить атрибут другой, но связанной модели, используемой в контроллере.
Как мне это сделать? Я не могу изменить маршрут, так что есть способ отправить другую переменную, которая получает [: params]?
И если я это сделаю, что мне делать в контроллере, настройте оператор case?
Ответы
Ответ 1
Вы можете создавать несколько кнопок отправки и предоставлять каждому из них разные значения:
<% 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
Однако помните, что это тесно связано с вашим взглядом на контроллер, который может быть не очень желателен.
Ответ 2
Существует также другой подход, используя атрибут formaction на кнопке submit:
<% form_for(something) do |f| %>
...
<%= f.submit "Create" %>
<%= f.submit "Special Action", formaction: special_action_path %>
<% end %>
Код остается чистым, поскольку стандартная кнопка создания не нуждается в каких-либо изменениях, вы вставляете только путь маршрутизации для специальной кнопки:
formaction:
URI программы, обрабатывающей информацию, представленную элементом ввода, если это кнопка отправки или изображение. Если указано, он переопределяет атрибут действия владельца формы элемента. Источник: MDN
Ответ 3
Вы также можете распознать, какая кнопка была нажата, изменив имя своего атрибута.
<% 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]
в зависимости от того, какой из них был нажат.
Ответ 4
Аналогичное решение для одного из предложенных @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
Обратите внимание, что я избегаю использования значения и использую имя ввода вместо этого, поскольку значение кнопки отправки часто интернационализируется/переводится. Кроме того, я бы не использовал слишком много, так как он быстро загромождает ваш файл маршрутов.
Ответ 5
Мы решили использовать расширенные ограничения в рельсах.
Идея состоит в том, чтобы иметь один и тот же путь (и, следовательно, один и тот же маршрут и действие), но с ограничениями, связанными с различными действиями.
resources :plan do
post :save, constraints: CommitParamRouting.new("Propose"), action: :propose
post :save, constraints: CommitParamRouting.new("Finalize"), action: :finalize
end
CommitParamRouting
- это простой класс, который имеет метод matches?
, который возвращает true, если параметр commit соответствует данному экземпляру attr. значение.
Это доступно как драгоценный камень commit_param_matching.
Ответ 6
Старый вопрос, но поскольку я имел дело с той же ситуацией, я думал, что отправлю свое решение. Я использую константы контроллера, чтобы избежать появления несоответствий между логикой контроллера и кнопкой просмотра.
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 %>
Таким образом, текст живет только в одном месте - как константа в контроллере. Однако я не пытался понять, как это сделать.
Ответ 7
У меня есть переменное количество кнопок отправки в моей форме благодаря nested_form_fields, поэтому просто использовать имя было недостаточно для меня. Я закончил, включая скрытое поле ввода в форме и используя Javascript, чтобы заполнить его, когда была нажата одна из кнопок отправки формы.