Как создать несколько кнопок отправки для одной и той же формы в Rails?


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

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

одна кнопка создает его как нормальный.

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

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

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

7 85

7 ответов:

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

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

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

есть и другой подход, используя атрибут formaction на кнопке submit:

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

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

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

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

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

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

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

мы решили с помощью дополнительные ограничения в рельсы.

идея состоит в том, чтобы иметь один и тот же путь (и, следовательно, одно и то же имя route & action), но с ограничениями маршрутизации на разные действия.

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.

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

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 для его заполнения, когда была нажата одна из кнопок отправки формы.