ruby-on-railsformsstimulusjsform-with

Rails 7 : Multiple forms/buttons on one page, each one supposed to trigger same action but with different input, always triggers the first in list


Here's the issue I'm facing. I'm creating miniature cards for my models, iterate on every item of the collection (using render @models) and each one has a button to trigger a form (POST) that goes to my controller action, and adds its id to my session cookies. However, now I notice that, whereas I didn't change any value on this side, it keeps triggering the same form in the iteration, the 1st (my controller always adds the value "1" to my form).

I'm using Rails 7, Ruby 3.1.1 and it started doing this for no reason. I was implementing Stimulus Controllers (to add AJAX responsiveness) when it just started bugging.

Here's a part of my form :

    <%= form_with(url: devis_path, method: :post, remote: true, data: {manage_cart_target: "form", action: "submit->manage-cart#manage"}) do |f| %>
      <%= f.hidden_field :tool_id, value: tool.id %>
      <%= tool.id %> # this part works and does display the expected value
      <%= f.submit "Ajouter à mon devis", class: "mt-4 text-xl w-full text-white py-2 rounded-xl shadow-lg cursor-pointer hover:bg-indigo-400", style: "background-color: #3949ab" %>
    <% end %>

And here's the part of my controller that's involved :

 def manage
    puts params # that's how I confirmed that it always sent "1" and none of the other ids on the page
    unless session[:cart]
      session[:cart] = []
    end
    # * If requests arrives with an index in params, it means it's to be deleted
    if params[:index]
      index_to_delete = params[:index].to_i
      session[:cart].delete_at(index_to_delete)
    end

    # * otherwise, if request arrives with a tool_id it's pushing it in the cart array
    if params[:tool_id]
      session[:cart] << params[:tool_id].to_i
      flash[:notice] = "Hey !"
      respond_to do |format|
        format.json
      end
    end

  end

It is a design choice not to create any record or to use any model for this and to store the value in cookies rather than DB.

Thanks in advance for any help. :)


Solution

  • The Problem is, that all the fields in your forms have the exact same ID, even if the actual url of your form_with is different and even if there are multiple forms. the requests intefer. You can work around that problem by assigning the inputs or in your case the hidden_field a unique id.

    <%= f.hidden_field :tool_id, value: tool.id, id: "tool_id_#{tool.id}" %>

    If you are planning on adding a label at some point you need to assign that id as for: for that label too.

    <%= f.label :tool_id, for: "tool_id_#{tool.id}" %>

    Hope that helps.