Submit <Ul> List as Parameter Array in Rails 4 Form, Adding Params Values to Params Hash Using JavaScript

Submit ul list as parameter array in Rails 4 form, adding params values to params hash using javascript

I was overthinking this and found a much easier answer. It has been a long time since I've worked on this so I've had to go back over my work to refresh my memory.

Basically I had the Javascript that builds inserts the default parts and any parts added as just a list of checkboxes with their boxes already checked. That way if the user decides they don't need one of the default parts, or want to remove a part they can just uncheck the box and it doesn't get submitted with the form. The empty checkbox lists start out in form shown above like this:

     Default Parts:<br>
<div id="default_parts_list" class="checkbox inline">

</div>
<br>
Other Parts:<br>
<div id="parts_expended" class="checkbox inline">

</div>
<br>
<br>

when the dropdown for the type of service is changed on the form it fires the javascript shown in my question above. This gets the parts list and hands it off to this JS:

$("#default_parts_list").empty();

$("#default_parts_list").append('<%= escape_javascript(render :partial => 'get_default_parts' ) %>');

which renders the _get_default_parts partial thus:

  <%= collection_check_boxes(:service, :part_ids, @parts_list, :id, :sku_name, {}, {checked: true}) do |b| %>
<%= b.label { b.check_box + b.object.name + " " + b.object.sku} %>
<% end %>

this creates html appended to the form like this:

<div id="default_parts_list" class="checkbox inline">

<label for="service_part_ids_14">
<input checked="checked" id="service_part_ids_14" name="service[part_ids][]" type="checkbox" value="14">Stihl/Denso Spark Plug W22mp-u 042511060272
</label>

<label for="service_part_ids_24">
<input checked="checked" id="service_part_ids_24" name="service[part_ids][]" type="checkbox" value="24">Bar Oil - Stihl 795711145835
</label>

<label for="service_part_ids_10">
<input checked="checked" id="service_part_ids_10" name="service[part_ids][]" type="checkbox" value="10">Stihl MS660/066 Air Filter 795711478179
</label>

<input name="service[part_ids][]" type="hidden" value="">
</div>

So they are just plain old checkboxes that end up being submitted with the form and end up in the params hash like this:

Parameters: {"utf8"=>"✓", "authenticity_token"=>"IHXcV0H8NnySxGIBXi8ZA=", 
"service"=>{"tool_id"=>"121", "name"=>"refresher", "due_date"=>"2014-12-27",
"completed"=>"2014-12-27", "service_type_id"=>"2",
"part_ids"=>["14", "24", "10", ""], "note"=>""}, "parts_used"=>"",
"commit"=>"Create Service", "tool_id"=>"121"}

When this same form is used to edit and exiting service it has to use a different form rather than the form partial above. The edit form looks like this:

<h1>Editing service for <%=" #{@tool.category.name.singularize} / #{@tool.serial}" %></h1>

<%= form_for ([@tool, @service]) do |f| %>
<% if @service.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@service.errors.count, "error") %> prohibited this service from being saved:</h2>

<ul>
<% @service.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>

<div class="row">

<div class="span4 offset1">

<div class="form-inline">
<%= f.hidden_field :tool_id , :value=>params[:tool_id] %>
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<br>
<br>
<div class="form-inline">
<%= f.label :due_date %><br>
<%= f.text_field :due_date, 'data-behaviour' => 'datepicker' %>
</div>
<br>
<br>
<div class="form-inline">
<%= f.label :completed %><br>
<%= f.text_field :completed, 'data-behaviour' => 'datepicker' %>
</div>
<br>
<div class="field">
<%= f.label 'Service Type:' %>
<%= f.select :service_type_id, ServiceType.all.collect{|s| [s.name, s.id] }, {include_blank: false} %>
</div>
<br>

</div>

<div class="span7">
<div class="form-inline">
<div class="part_list_element">
Parts Used <br>
<%= text_field_tag :parts_used %>
</div>
</div>
<br>
<strong class="alert-danger">Any parts that get unchecked here will be returned to inventory</strong><br>
<b>Parts Used:</b> <br>
<div id="parts_used_list" class="checkbox inline">

<%= f.collection_check_boxes :part_ids, @service.parts, :id, :name %>

</div>
<br>
<b>Other Parts:</b> <br>
<div id="parts_expended" class="checkbox inline">

</div>
<br>
<br>

<div class="form-inline">
<%= f.label :note %><br>
<%= f.text_area :note %>
</div>
<br>
<br>
<div class="actions">
<%= f.submit %>
</div>

</div>
</div>

<% end %>

I hope this helps anyone doing something similar. You can view the full source app on github:
EquipDB on github.com

Can I pass params from button submit in Rails 4?

You are trying to submit a form, let's do it in Rails way,

<%= form_for :points, points_path do |f|  %>
<%= f.text_field :name %>
<%= f.submit %>
<% end %>

In the action you can access the name param by params[:points][:name]

Hope that helps!

How to pass an array of param values via GET to a controller action

For strong parameters to permit an array of id, you could try

def query_params
params.permit(id: [], :name)
end

For URL to send an array of ids

http://my.app/api/users?id[]=1,2,3

How to accept multiple values into the same key parameter, as an array?

Thank you to @TarynEast and @mu_is_too_short for their comments on this! You both are so kind with your time and StackOverflow is better for having you in its community! :) Thank you thank you!

Now, on to the solution...

Since I was setting up array variables (ie key and value) to temporarily store parameters that were not directly part of the Documents table, the solution was two-fold.

First I had to properly initialize these variables before using them in the controller.

At first, I experimented in document.rb with

def initialize 
@key = Array.new
@value = Array.new
end

but this threw some argument errors. I'm not sure why exactly, but I suspect Rails 5 frowns on the use of initialize since ActiveRecord uses it further up the chain to automatically set up attr_accessor methods...

So then I modified the array creation to use callbacks, and that did the trick!

document.rb

after_initialize :create_key, :create_value

def create_key
@key = Array.new
end

def create_value
@value = Array.new
end

Then, with the variables properly set up as arrays, the form now let me name the fields with array references (previously, it rightly complained about key and value being strings).

_form.html.erb

<%= document_form.text_field :key, name: "key[]" %>
<%= document_form.text_field :value, name: "value[]" %>

Thoughts? Critiques? Improvements? I'm all ears and willing to learn :)

convert array of parameters from form into string

It shouldn't be a problem, since ?producers[]=4&producers[]=5 will be converted by the framework into params[:producers] array with value [4, 5].

Thus, you already have an array and you don't even have to parse anything.

But if your really want to submit two input values in one parameter, you'd have to employ some javascript. By default, if you have in html form two inputs with the same name, two independent values will be submitted (like in sample url you provided).

So, it's not a Rails question, it's html and javascript question.

Passing array of parameters through get in rails

No, GET can only put variables on the url itself. If you want the URL to be shorter, you have to POST. That's a limitation feature of HTTP, not Rails.

Params hash from a SimpleForm with multiple records has a different structure for one record than for two

It turns out that the f.simple_fields_for 'courses[]' ... method only gives that fieldset an ID if the form is populated by an existing record, and the params structure of a string ID mapping to a course hash is only used in this case. For "fresh" records, there is no ID and the course hashes are placed in a plain array.

This bit of code was running in the context of "rolling over" courses from one year to another - copying a previous course and changing the dates. This meant that each fieldset had the ID of the original course.

When the form was submitted, a new record was created and validated with the new attributes, and it was this fresh record with no ID that repopulated the form. The "it only happens when one course is submitted" thing was a red herring - a product of the test scenario.

So worth noting: f.simple_fields_for 'courses[]' ... creates an array for new records and a hash mapping IDs to attributes for existing records.



Related Topics



Leave a reply



Submit