I'm trying to setup a formtastic form with multiple submit actions, following along with Railscast #38. What's the equivalent of this in Formtastic?
<%= submit_tag 'Create' %>
<%= submit_tag 'Preview', :name => 'preview_button' %>
This post gave me hope, but it looks like commit_button was deprecated in 2.1.0, and I can't seem to figure out the new syntax.
Here's my code for what it's worth. I'd like each submit button to go to the same controller, where I will handle them differently:
# Use prepaid credits to checkout
<%= f.action :submit, :as => :button, :label => "Order Critique (1 credit will be spent)", :button_html => { :class => "btn btn-primary", :disable_with => 'Processing...' } %>
# Use credit card to checkout
<%= f.action :submit, :as => :button, :label => "Order Critique ($10)", :button_html => { :class => "btn btn-primary", :disable_with => 'Processing...' } %>
TL;DR: If you use javascript to submit a form, it won't carry over the submit button's name in the commit params.
My problem ended up being the code used in Railscasts Episode #288. This CoffeeScript function gets fired when you submit the form, after the Stripe token checks out:
handleStripeResponse: (status, response) ->
if status == 200
$("#stripe_card_token").val(response.id)
$("#my_form_id")[0].submit()
else
# other stuff
Since javascript is doing the form submission with $("#my_form_id")[0].submit(), the name parameter won't be carried over in the commit params.
My solution was to add a "clicked" attribute to the button that gets clicked...
$('form_input[type=submit]').click ->
$('input[type=submit]', $(this).parents('form')).removeAttr('clicked')
$(this).attr('clicked', 'true')
..and then grab the id attribute of the clicked button populate a hidden field with it:
submitter = $("input[type=submit].clicked=true").attr("id")
I don't particularly like this solution. It feels like my js knows too much, and I don't like depending on js for this sort of thing. Any criticism or better solutions are certainly welcome :)
Related
I have a problem when trying to submit a form with a div (instead of a f.submit button)
<%= form_for #user, url: {action: "submit_user"}, html: {id: "user_submit", class: "form"}, :method => "post" do |f| %>
<%= f.text_field :first name, :required => true, :placeholder => 'first name', :autocomplete => :off %>
<%= f.text_field :last name, :required => true, :placeholder => 'last name', :autocomplete => :off %>
<div id="submituser" class="some very fancy css here" onclick = "document.forms['user_submit'].submit();">
<% end %>
The problem is that the form is sent, but without the validations (causing it to send blank first and last name if nothing is entered)
note that when using
<% f.submit "submit" %>
validations do work.
Thanks
I guess document.forms['user_submit'].submit(); does not trigger the submit event, so You have to launch validation manually. But what is the point of using div instead of button? You could style a button with some very fancy css here too. OR make a 'hidden' submit button and add onclick = "document.form.button.click()" to div :-)
Found my answer here:
Difference between handling $(“form”).submit or an click event?
And i quote #Giovanni Sferro:
The click callback is called only if the user actually click on the submit button. But there are cases in which you would submit the form automatically by javascript, in that case the click callback is not fired while the submit callback is. I would recommend to use always the submit for validation and intrinsic action of the form, while using the click callback for animation or other things related to the action of clicking on the button.
so my (working) code looks like this:
<div id="submituser" class="some very fancy css here" onclick = '$("#user_submit input[type=\"submit\"]").click();'>
Let's say I'm in a new action and want to pass some extra information to the create action (for instance, how many times a user has pressed a given button, :clicks).
How should I go about accomplishing the task?
Try:
<%= hidden_field_tag 'click_count', 0 %>
<%= submit_tag "Click me!", :type => 'button', :onclick => '$("#click_count").val(parseInt($("#click_count").val())+1)' %>
The following works great for carrying forward data from one page to another:
<%= link_to 'New Work Order', new_workorder_path, :class => 'btn btn-primary', :onclick => session[:worequest_id] %>
How would I add a 2nd field? The following doesn't work:
<%= link_to 'New Work Order', new_workorder_path, :class => 'btn btn-primary', :onclick => session[:worequest_id] = #worequest.id, [:client_id] = #worequest.client_id %>
Thanks!
UPDATED
This is the code I'm using in the new work order form. It picks up the worequest_id field from the session
<% if session[:worequest_id] != nil %>
<%= f.hidden_field :worequest_id, :value => session[:worequest_id] %>
onclick doesn't really work this way – it's an html attribute used to store JavaScript code to be executed when the element is clicked. While you can use it to evaluate Ruby code in the context of a Ruby method call (in this case as part of the options hash given to link_to), it doesn't really make sense to do so.
In your first example, it doesn't actually do anything. If you check your rendered html on the page where that link appears, I expect it evaluates to something like New Work Order. You can, however, store data in session (which is persistent for as long as the user remains logged in), which is why you're seeing this data carrying forward from page to page.
If you're trying to fill in default values for the new workorder, you could pass them as params to the path method:
link_to 'New Work Order',
new_workorder_path('workorder[worequest_id]' => #worequest.id,
'workorder[client_id]' => #worequest.client_id),
:class => 'btn btn-primary'
In your workorders#new action, your model instantiation would need to include the params:
def new
#workorder = Workorder.new(params[:workorder])
end
However, this might not be the best way to proceed. If there will always be a client or worequest associated with a workorder, you might want to look into nested routes.
I have run into a bit of a problem and a head scratcher, as I'm not sure whether what I want to do is even possible with RoR.
A bit of background info: I have an app with several controllers... and would like to work with 2 of them for this modal example. The first is a users_controller and the other is a recommendations_controller.
Here is what I'm trying to do: In the user index view I have a lists of posts. Each post has a recommend button. If a user clicks it he/she is sent to the recommendation index page, and can search and find a user he/she would like to share the post with. The reason I have it set up this way is because the Recommendation model creates the recommend relationship.
I would like like it so when the user clicks the recommend button on the User index page, a modal appears (one that accesses the recommendation controller) and the user can search for the user he/she would like to share the post with. Basically, I want to know whether it's possible to access the Recommendation controller via the User controller's index view page.
If it's not, is there a work around? I can post the code I have if it's helpful, but I'm not sure that would help in this case--as I'm trying to see whether it's even possible to do what I'm trying to do.
Thank you!
More Details:
recommendations_controller:
def index
#user = Search.find_users(params[:name], current_profile)
respond_to do |format|
format.html
format.js
end
end
index.js.haml (located in the view/recommendations folder)
:plain
$(#my-modal).show();
index.html.haml (located in the view/recommendations folder)
= form_tag post_recommendations_url, :method => "get" do
= text_field_tag :name, '', :class => "span12", :placeholder => "Please enter the name of the users you would like to share this post with."
%center
= submit_tag "Search", :class => "btn btn-primary"
index.html.haml (located in the view/posts folder)
%a{:href => "#{post_recommendations_path(post)}", :remote => true}
%i.icon-share.icon-large
Recommend Post
#my-modal.modal.hide.fade
.modal-header
%a.close{"data-dismiss" => "modal"} ×
%h6 This is a header
.modal-body
%p This is where I would like the contents of the index.html.haml file, located in the view/recommendations folder to appear.
Part 2: Displaying the search results inside the modal/partial
Matzi, at the moment, a user clicks a link near the post they want to recommend. This link renders the modal with a partial (_recommendation.html.haml) inside of it.
This partial (now inside the modal) contains the search form_tag and the code to render all the users that match the search results. Unfortunately, when I try to run a search by entering a name and clicking the search button (again, now located inside of the modal) it takes me to the following url instead of rendering the results inside the modal.
http://localhost:3000/posts/2/recommendations?utf8=%E2%9C%93&name=Test&commit=Search
here is what my updated index.html.haml (located in the view/posts folder) looks like:
= link_to 'Recommend Post', post_recommendations_path(post), :remote => true, "data-toggle" => "modal"
#my-modal.modal.hide
.modal-header
%a.close{"data-dismiss" => "modal"} ×
%h6
%i.icon-share.icon-large
Recommend Post
.modal-body
#modal-rec-body
%p *this is where _recommendation.html.haml is rendered*
updated index.js.haml
:plain
$("#modal-rec-body").html("#{escape_javascript(render('recommendations/recommendation'))}");
$('#my-modal').modal({
keyboard: true,
show: true
});
_recommendation.html.haml
.span12
= form_tag post_recommendations_path, :method => "get" do
= text_field_tag :name, '', :class => "span12", :placeholder => "Please enter the name of the user you would like to share this post with.", :style => "max-width:520px;"
%center
= submit_tag "Search", :class => "btn btn-primary", :remote => "true"
- #user.each do |i|
- unless current_profile == i
.row-fluid
.span6
.row-fluid
.well{:style => "margin-left:0px;"}
.row-fluid
.span2
=image_tag i.avatar(:bio), :class=> "sidebar_avatar"
.span6
%dl{:style => "margin:0px"}
%dt
%i.icon-user
Name
%dd= i.name
%dt
%i.icon-map-marker
Location
%dd= i.location
.span4
- form_for :recommendation do |r|
= r.hidden_field :friend_id, :value => i.account.id
= r.submit "Send Recommendation", :class => "btn btn-primary"
Problem: Unfortunately it seems that when I click the submit (search) button inside the modal instead of rendering the results inside the modal it re-directs the browser to the post_recommendations_path (posts/post.id/recommendations). I would like to display the search results inside the modal without having it redirect to the post recommendations path.
As always, thank you so much! I'm extremely grateful for your help--and I've gotten a much better grasp for AJAX thanks to you. Thank you!
Of course you can do this, but it needs some ajax magic.
First of all, you need to create an action, responding to .js requests, in the recommendation controller. It is done so far in your update. But, your .js is not quite right. The problem is that you render the modal form from the post view, but propably in post controller you dont have the right fields. I recommend the following .js.erb:
$("#modal-body").html(<%= escape_javascript render(:partial => 'recommendations/index')%>);
$("#my-modal").show();
This fills the modal with the form. The next step is to do a remote request from this form. Modify your posts/index the following way:
= form_tag post_recommendations_url, :remote => true, :method => "get" do
= text_field_tag :name, '', :class => "span12", :placeholder => "Please enter the name of the users you would like to share this post with."
%center
= submit_tag "Search", :class => "btn btn-primary"
The difference is the :remote => true tag, this sends an ajax request to your controller, so you must prepare for .js and .html response (in case of no JS on client). The .js should hide the modal form, and may refresh the original page, the html may redirect you back to the post.
Part 2:
The problem is the :remote part. It needs to be part of the form's definition, not the submit button's. My mistake.
I found this guide now, it seems quite good.
I hope it helps! Ask if something is not clear.
I am trying to make sure the users of my rails app can not submit my formtastic forms multiple times by double clicking.
See my code below.
Unfortunately, after adding the :onclick argument to the commit button, the form does not process anymore. The button name simple changes to a disabled button 'Processing...' (as expected during submission) but this state is permanent (no data validation and redirect as before).
I fail to see how to debug this - can anybody help?
= semantic_form_for #case, :html => {:class => "form-stacked"} do |f|
= f.inputs :name => "Case" do
= f.input :summary, :input_html => {:class => 'xxlarge main_case'}
= f.buttons do
= f.commit_button "Create Case", :button_html => {:class => "btn primary", :onclick => "this.disabled=true; this.value='Processing...';"}
just try:
submit_tag "Create Case", :disable_with => "Processing..."
this will work in rails 3 and above
Update:
with formtastic you need the following
<%= f.action :submit, :button_html => { :label => "create case", :class => "btn primary", :disable_with => 'Processing...' } %>
If you are not using rails 3, you would actually want to do that on "onsubmit" on the form element, since pressing enter keys in text fields etc can trigger submit event.
Make sure you "return true" in your js code for the form to actually submit after you disable the button.