Rails Trying to submit a form onchange of dropdown - ruby-on-rails-3

I have my Ajax working, builtin Rails javascript, with the submit button. However, I would like it to submit when I change the value of the dropdown box and eliminate the button. In my research I found what looks like the correct solution but I get no request to the server. Here is my dropdown form code, note it still has the submit button that worked before I added :onchange:
<% form_tag('switch_car', :method => :put, :remote => true) do %>
<div class="field">
<label>Car Name:</label>
<%= select_tag(:id, options_from_collection_for_select(active_cars, "id", "name"),
:onchange => ("$('switch_car').submit()"))%><%= submit_tag "Switch Car" %>
</div>
<% end %>
Here is the HTML generated:
<form accept-charset="UTF-8" action="switch_car" data-remote="true" method="post">
<div style="margin:0;padding:0;display:inline">
<input name="utf8" type="hidden" value="✓" />
<input name="_method" type="hidden" value="put" />
<input name="authenticity_token" type="hidden" value="PEbdqAoiik37lcoP4+v+dakpYxdpMkSm7Ub8eZpdF9I=" />
</div>
<div class="field">
<label>Car Name:</label>
<select id="id" name="id" onchange="$('switch_car').submit()">
<option value="9">Truck</option>
<option value="10">Car</option>
</select>
<input name="commit" type="submit" value="Switch Car" />
</div>
Thanks in advance for any help.

Replace your onchange with this,
onchange: "this.form.submit();"

this.form.submit() will not work if form is remote: true and rails-ujs is in use. In that case, a regular submit will occur instead of XHR.
Instead you should:
onchange: 'Rails.fire(this.form, "submit")'
You can read here for more details.

This is what I was able to do to get it to work. I named the form switch_car by using :name => "switch_car" and used the following javascript.
:onchange => ("javascript: document.switch_car.submit();")
I am still looking for a better answer so I will updated if I find something. This doesn't use submit .js for some reason. It processes it as HTML unlike the submit button which uses AJAX to update only the changing page elements. But this is the best I have been able to find so far.

Depending on the js library you are using:
Prototype: :onchange => ("$('switch_car').submit()")
Jquery: :onchange => ("$('#switch_car').submit()")
If you are using the defaults and your rails version is below 3.1, then prototype is the default library.

This is an old question, but none of the above answers work for me. They all result in a text/html request.
The following works, e.g. (the hide class sets css display: none):
<%= form.radio_button :tier_id, tier.id, onchange: "$('#submit-button-id').click();" %>
together with:
<%= form.submit "Save changes", id: 'submit-button-id', class: 'hide' %>

A more general solution using jQuery (I don't need to know the name of the form) is:
onchange: "$(this).parent('form').submit();"

This seems to have been around for a while but, I'll post my findings anyway since I haven't found this explanation anywhere yet.
I came across this article which describes quite well what's the problem when triggering a ajax request via the submit() method (with or without jQuery or Handler). The author then recommends to form your own AJAX request. That is not required and shouldn't be done to make use of the logic within rails.js (jquery-jus gem).
Problems with triggering submit() manually occur since rails.js binds and listens to an event that is namespaced submit.rails. To manually trigger a submission use
onchange: 'javascript: $( this ).trigger("submit.rails")'
on the element or the form.

For a select_tag, just add:
{:onchange => "myHandler();" }
where your handler will be:
this.form.submit();
Also, if onchange doesn't work you might want to try onChage with a capital C.
Finally, make sure NOT TO CONFUSE a select_tag with a form select.
See my answer to a similar question, only regarding a form select
Adding An Onchange Event To A Form Select

Time at 2021, with Rails 6
make a hidden submit then use js click() function:
<%= form_with(modle: #user, local: false) do |f| %>
<%= f.select :menu1, ["option1","option2"], {}, onchange: "javascript:this.form.commit.click();" %>
<%= f.submit 'save', class: "hidden" %>
<% end>
reference: https://stackoverflow.com/a/8690633/15461540

If you want to learn rails way ajax submit on fields change here is the code.
<%= select_tag(:id, options_from_collection_for_select(active_cars, "id", "name"),
data: { remote: true, url: your_ajax_route_path }%><%= submit_tag "Switch Car" %>
data: { remote: true, url: your_ajax_route_path }
will automatically submit your input to your_ajax_route_path. If you are using a form builder then you should use with input_html
input_html: { data: { remote: true, url: your_ajax_route_path } }
like this. I hope it'll be useful for you

None of the solutions was working for me so I used the given below solution.
$("#q_dimension_id_eq").on("change", function (e) {
$(this).closest("form").submit();
});

I'm using rails 4.2.1 with jquery_ujs and it works for me:
onchange: 'jQuery(this).parent().trigger("submit")'
OBS.: It assumes the element is immediately child from form. You must adjust parent() according your DOM tree.

Related

Capybara: Unable to find css for collection_select and text_field_tag

I have a collection_select and text_field_tag like this:
<%= form_tag method_path(#test.id), method: :get do %>
<%= collection_select(:test, :id, Test.all, :id, :id, prompt: true, include_blank: 'Select Test') %>
<%= text_field_tag(:input_test_questions, 'Test ids') %>
<%= submit_tag "Add" %>
<% end %>
This generates the following html:
<select name="test[id]" id="test_id"><option value="">Select Test</option>
<option value="1">1</option>
<option value="2">2</option>
</select>
<input type="text" name="input_test_questions" id="input_test_questions" value="Test ids">
<input type="submit" name="commit" value="Add">
I am trying to write integration test using Capybara for the above. To select and input I wrote like this:
select "2", from: "#test_id"
fill_in "input_test_questions", with: "1"
But I am getting the following errors:
Capybara::ElementNotFound: Unable to find css "#test_id"
Capybara::ElementNotFound: Unable to find field "input_test_questions" that is not disabled
How can I rectify the error so that Capybara finds and selects and fills with the above options?
The from option of select is used to locate the <select> element by its name, id, test_id attribute, or label text. It does not take a CSS selector.
select "2", from: "test_id" # find by id
select "2", from: "test[id]" # find by name
fill_in "input_test_questions", with: "1" should work as written against the HTML shown, unless you have JS/CSS behavior that is hiding the text input on the page. If you are hiding it then Capybara can't fill it in because a user wouldn't be able to.
Note: It shoudln't really be possible for the error message you show Capybara::ElementNotFound: Unable to find css "#test_id" to come from the code you show, unless you're using a REALLY old version of Capybara. Hopefully that was just an incorrect copy/paste from other attempts you made.

Rails 5 - use collection_radio_buttons to open a partial with nested models?

(my first SO question, so please be kind!)
Each Schedule has only one System;
Each System has many Applications;
Each Application has many Users and Documents.
What I want to do to create a Schedule entry:
Generate a form that first shows multiple System names that can be clicked. When a System is clicked, it opens a partial that lists Applications associated with that System. Then, when clicking particular Applications, yet another partial opens that contains Users and Documents associated with that particular Application.
When editing this entry later, I want to be able to see everything I had entered before, with the correct System, Application(s), User(s), and Document(s) already pre-selected.
My question here is how to make a form element for choosing a System that will open another partial -- and, later, will be pre-selected when I view and/or edit the entry.
What kinda works right now is a <%= link_to %>, styled with Bootstrap, which opens its associated Applications partial when it's clicked. However, I'm not able to save the System from it, and I can't figure out whether it can display as already-selected later, such as in an Edit form.
We're trying to use radio buttons instead (because you can't pre-select a link_to, right?), so I've been throwing pasta at the wall with f.collection_radio_buttons, or iterating over f.radio_button, or a tag of <input type="radio">. However, I can't figure out how to make a radio button open a partial.
Since first posting this question, I've narrowed down to using f.radio_button within a loop. It shows as correctly "checked" when viewed while Editing the entry later, but it still doesn't open the partial.
Here's a snippet from /_schedule_form.html.erb:
<%= form_for #schedule do |f| %>
<% System.all.each do |a| %>
<!-- This link_to makes the Applications partial appear, but that's all it does -->
<%= link_to a.system_nm, system_applications_path(:system_id => a.id,
:schedule_id => params['id']), :title => 'Click to choose system',
:class -> 'btn btn-default btn-flat active', data: {:remote => true,
'data-target' => '#applicationList'} %>
</a> <!-- closes the link_to tag, I believe -->
<% end %>
<div id="applicationList">
<!-- the Applications partial renders here -->
</div>
<% end %>
Here's the system_applications.js.erb file that opens the _system_applications.html.erb partial:
$("#applicationList").html("<%= escape_javascript(render
'system_applications', locals: {applications: #applications,
schedule_applications_array: #schedule_applications_array})%>");
Here's an update with possible clue:
I'm now using this embedded Ruby code:
<% System.all.each do |rt| %>
<label>
<%= f.radio_button :system_id, rt.id, data:{:remote => true, 'data-target' =>
'#applicationList'}, href: system_applications_path(:system_id => rt.id,
:schedule_id => params['id']), class: 'remote-input', onclick:
"#applicationsList" %>
</label>
<% end %>
And, when I click on that radio button, I'm getting a JS error in the browser console Uncaught SyntaxError: Invalid or Unexpected Token which points to the rendered HTML, and specifically the > at the end of the line:
<input data-remote="true" data-data-target="#applicationList" href="/schedules/system_applications/24?schedule_id=122" class="remote-input" onclick="#applicationList" type="radio" value="24" checked="checked" name="schedule[system_id]" id="schedule_system_id_24" />
Just to make it more complicated:
When creating a NEW entry, and when I hover over one of the link_to buttons, I get a clean-looking path like /schedules/system_applications/24, and that's what gets sent to the server when clicked (which then reads the params as {"system_id"=>"24"}. But hovering over the f.radio_button labels shows no path, and clicking it sends "/schedules/new?schedule%5Bsystem_id%5D=24" with the params {"schedule"=>{"system_id"=>"24"}}. This triggers a 500 (Internal Server Error) (which makes sense, because there's no path for that URL). Do the params need to be the same? If so, how am I screwing it up?
Also, clicking the radio button sends the request to SchedulesController#new, while clicking the link_to sends it to SchedulesController#system_applications. I don't understand how I'm telling the radio button to send it to #new.
Where I'm stuck now is, the f.radio_button renders as "checked", which is correct; but it doesn't open the partial. The link_to version opens the partial, but I don't think it can render as "checked" later on.
Let me know if I'm asking clearly enough, too.
I think we made it work. One key change was to use url instead of href to use the system_applications_path to the controller, as shown here:
<% #systems.each do |a|
<label class="btn btn-sm btn-default">
<%= f.radio_button :system_id, a.id, :data => {url:system_applications_path(:system_id
=> a.id, :schedule_id => params['id']), 'data-target' => '#applicationList'+a.id.to_s,
:remote => true} %>
<%= a.system_nm %>
</label>
<% end %>
Now, when I click the radio button, it opens the correct partial, and it shows as selected later when I go to edit the entry. The Bootstrap styling (btn btn-sm btn-default) helps to show how much clickable area there is, but it's not required for basic functionality.
I suppose some of that [in]famous Rails Magic has radio_buttons treating href: differently than url. But it's "magic" only because I don't understand it (yet -- growth mindset!). What's the explanation behind it?

Bootstrap: Format <form> inside drop down

In the Phoenix framework, if I create a delete button (using the link helper function) then it generates a form element.
However, if I put this code inside a Bootstrap drop down, then it's not rendered as a menu item.
I tried using the :form parameter to remove the "button" class, like so:
<ul class="dropdown-menu" aria-labelledby="dLabel">
<li>Insert above</li>
<li>Insert below</li>
<li role="separator" class="divider" />
<li><%= link "Delete", to: log_path(#conn, :delete, log), method: :delete, data: [confirm: "Are you sure?"], form: [class: ""] %></li>
</ul>
This didn't help much. When I inspected the element using Chrome, it seems that Bootstrap menus are looking for the css selection - .dropdown-menu>li>a
Is there another class I could take advantage of for the form? What's the best way to address this with Bootstrap?

How do I set two different actions from a rails form?

I have a rails form that creates (and updates) materials. Obviously, by default, when the user is logged in and the materials is retrieved the form renders with the update action. However, I want to have a "save as" action in case the user wants to save another version of the material. The obvious way to do this is to have one button which sends to 'update' in the controller and another which sends to 'new', but I don't know how to do this since it seems to depend on the form_for parameters.
Update
To avoid using Javascript I tried changing the form_for url to:
<%= form_for #material, :url => choose_action_path do |f| %>
Then in the controller I have:
def choose_action
if params[:save_as] == "Save As"
redirect_to :action => "create"
else
redirect_to :action => "update"
end
end
but this is not working. Is this a strategy that could work or is this crazy?
You could probably do this with some jquery.
Let's say the model you are working on is called Email. When you edit an Email, the form tag that is created with have an action action='/emails/:id and a method method='post'. Hidden underneath the form tag is something like
<form accept-charset="UTF-8" action="/email/1" method="post">
<div style="margin:0;padding:0">
<input name="_method" type="hidden" value="put" />
<input name="utf8" type="hidden" value="✓" />
<input name="authenticity_token" type="hidden" value="f755bb0ed134b76c432144748a6d4b7a7ddf2b71" />
</div>
more info can be found here: http://guides.rubyonrails.org/form_helpers.html#how-do-forms-with-put-or-delete-methods-work
That extra chunk of code makes the form submit a put request instead of a post, which subsequently maps to the update action of your controller. To get it to send the form to the create action, you want to post the action "/email". In other words, you want to manipulate the code above into something like
<form accept-charset="UTF-8" action="/email" method="post">
Note the removal of the div tag.
So my suggestion would be to create a button "Save As", then add some jquery which will make those modifications when the "Save As" button is clicked.
This stackoverflow answer might help you with the jquery Jquery to change form action

partial local only accessible using local_assigns, not exposed by name

I am passing two locals from a view ERB to a partial. Both locals are successfully passed in local_assigns. However, I am only able to use the FormBuilder via a local variable name in the partial. The other value is usable within my partial as local_assigns[:disable_edits], but not as disable_edits.
_form.html.erb
<div>
<%= f.fields_for :panels do |builder| %>
<%= render "panel_fields", :f => builder, :disable_edits => true %>
<% end %>
</div>
_panel_fields.html.erb
<div>
<p>
<%= local_assigns[:disable_edits] %>
</p>
<p>
<%#= disable_edits ? 'disable edits true' : 'disable edits false' %>
</p>
<p>
<%= local_assigns.keys %>
</p>
local_assigns[:disable_edits] results in "true" being displayed.
local_assigns.keys results in "[:f, :disable_edits, :panel_fields]" being displayed.
Uncommenting the ternary statement results in "undefined local variable or method `disable_edits' for #<#:0x4d58768>"
I am following what I understand is the latest suggested Rails syntax, but have tried manipulations using :partial=>, :locals=>, :as=>, etc. to no avail. I also do not think I've made this an optional argument in any way, so a lot of the information about testing with has_key vs. nil? isn't helping me. My understanding is everything in local_assigns should be exposed as in the partial as a local variable with the same name as the hash key.
I'm getting by for now using local_assigns[:disable_edits], but would like to understand what is happening and correct things so I can use more conventional syntax. Thanks!
try using
render :partial => "panel_fields", :locals => {:f => builder, :disable_edits => true }