Как создать несколько кнопок отправки для одной формы в Rails? - PullRequest
90 голосов
/ 12 июня 2010

Мне нужно иметь несколько кнопок отправки.

У меня есть форма, которая создает экземпляр Contact_Call.

Одна кнопка создает его как обычно.

Другая кнопкасоздает его, но ему нужно другое значение атрибута: значение по умолчанию, а также ему нужно установить атрибут для другой, но связанной модели, используемой в контроллере.

Как это сделать?Я не могу изменить маршрут, так есть ли способ отправить другую переменную, которую получает [: params]?

А если я это сделаю, что мне делать в контроллере, настроить оператор case?

Ответы [ 7 ]

125 голосов
/ 12 июня 2010

Вы можете создать несколько кнопок отправки и предоставить разные значения для каждой из них:

<% 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

Однако помните, что это тесно связывает ваш взгляд с контроллером, что может быть не очень желательно.

59 голосов
/ 12 сентября 2015

Существует также другой подход, использующий атрибут formaction на кнопке отправки:

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

Код остается чистым, поскольку стандартная кнопка создания не нуждается в каких-либо изменениях, вы просто вставляете путь маршрутизации для специальной кнопки:

formaction:
URI программы, которая обрабатывает информацию, представленную элементом ввода, если это кнопка отправки или изображение. Если указано, переопределяет атрибут действия владельца формы элемента . Источник: MDN

29 голосов
/ 22 апреля 2013

Вы также можете распознать, какая кнопка была нажата, изменив имя ее атрибута.

<% 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] в зависимости от того, какая из них была нажата.

12 голосов
/ 19 марта 2014

Аналогичное решение, предложенное @ 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

Обратите внимание, что я избегаю использования значения и использую вместо него имя ввода, поскольку значение кнопки отправки часто интернационализируется / переводится. Кроме того, я бы избегал использовать это слишком часто, так как это быстро загромождает ваш файл маршрутов.

9 голосов
/ 27 октября 2013

Мы решили использовать расширенные ограничения в рельсах.

Идея состоит в том, чтобы иметь один и тот же путь (и, следовательно, один и тот же названный маршрут и действие), но с ограничениями, маршрутизирующими к различным действиям.

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

CommitParamRouting - это простой класс, который имеет метод matches?, который возвращает true, если параметр коммита соответствует данному атрибуту экземпляра. значение.

Доступен как драгоценный камень commit_param_matching .

3 голосов
/ 25 июля 2014

Старый вопрос, но, поскольку я имел дело с той же ситуацией, я решил опубликовать свое решение.Я использую константы контроллера, чтобы избежать несоответствия между логикой контроллера и кнопкой просмотра.

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 %>

Таким образом, текст только живетв одном месте - как константа в контроллере.Однако я еще не пытался понять, как это сделать.

1 голос
/ 19 апреля 2016

У меня есть переменное количество кнопок отправки в моей форме благодаря nested_form_fields, поэтому мне просто было недостаточно использовать имя. В итоге я включил скрытое поле ввода в форму и использовал Javascript для его заполнения при нажатии одной из кнопок отправки формы.

...