Can I have inputs without forms in a Rails view? - html

I want to have a few check boxes on my page, and a link that accesses the value of these check boxes to pass in a link_to helper. I did not want to use a form because the view essentially has a number of links interspersed, and it doesn't naturally seem to be a form with one logical submit button.
I have something like
<% for p in #some_array %>
<!--other stuff .... -->
<input value=<%= p.id %> id=<%= p.id %> name="selected[]" type=checkbox>
<!--other stuff .... -->
<%= link_to "View all selected thing(s)", :action => 'show_selected', :selected_things => selected[] %>
But it doesn't seem to recognize the variable selected which stores the inputs. It raises
undefined local variable or method `selected' for #<#<Class:0x000001021b4a38>:0x00000102319a90>

I would say the last line in your code snippet is causing the error:
<%= link_to "View all selected thing(s)", :action => 'show_selected', :selected_things => selected[] %>
As ruby complains about a selected not being defined.
(Although I can't see why you don't want to use a form, as forcing the selections into something you can pass to the link would require some javascript magic.)

Related

Rails checkbox create a submit action

I have a rails form with checkboxes. What I am trying to do is when the user clicks on a check box the app deletes that entry from the database. What I cannot figure out is how to have the app react when the user checks on the check box (similar action to having a submit button clicked). What should I include in my html so when the user click on a check box the app does something?
Here is my code
<% #items.each do |item|%>
<%if item.email == #user.email%>
<%= form_for #item do |f| %>
<%= f.check_box :to_do %>
<%= f.label item.to_do %><br />
<% end %>
<%end%>
<%end%>
I am iterating through items and if there is a match between the item.email and user email print out the item with a check box next to it. I can include more code if needed. Is there an Ajax call I can make?
As RedBassett said, I'm not 100% sure I agree with the strategy of having a checkbox instantly delete an entry. However, if that form you have is already set up to delete things, you can do it like this:
You don't even need an AJAX call. Just regular Jquery. Add a class to the form, as well as to the checkbox
<%= form_for #item do |f|, :class => "form-class" %>
<%= f.check_box :to_do, :class => "checkbox-class" %>
and in your JS file, use Jquery to tell the form to submit when the user clicks the checkbox.
$(".checkbox-class").on("click", function (){
$(".form-class").submit();
});
Note: this will actually submit the form, it will be as if you checked the box and then pressed a 'submit' button, so you will need to handle the form submission in the controller, if you want to stay on the same page, you will need to redirect back to the same page as this action will cause a reload/redirect
Yes. You can write an AJAX call.
<script>
$('#checkbox_id').change(function(){
$.get('controller/action?item_id='+$(this).val(), function(data, status){
/* Call back */
})
})
</script>
Use borbesaur answer, but remember you can just add the remote: true option to your form so Rails can submit the form using ajax and you avoid reloading all the page again. :)

Ruby on Rails pass button value to next page

I am trying to design a webpage that contains both a radio button field and a list of links. When one of the links is clicked, I would like to pass the associated value of the button to a controller. So far I have the following code:
In my views page:
<div id="radio_buttons">
<%= radio_button_tag 'radioGroup', "1" %> 1
<%= radio_button_tag 'radioGroup', "2" %> 2
<%= radio_button_tag 'radioGroup', "4" %> 4
</div>
...
<div class = "text">
<%= link_to "mylink", search_path(:radioGroup => #radioGroup)%>
</div>
In my Controller:
#radioGroup = params[:radioGroup]
When I add the line 'puts #radioGroup' to my controller, it prints nothing. I have been able to pass different values to a new web page upon a link click (i.e those contained in a text field) but for some reason I can't figure out how to do the same thing with buttons. Does anyone know how to accomplish this?
Thanks!
If you want to submit multiple values to another page you should use an HTML form for it. Check this page for more related info: http://guides.rubyonrails.org/form_helpers.html.

What is the difference between using rails form_tag and html form code in an erb file?

I had a problem with a rails app I am making. It is an e-commerce site, and on the page where the user enters their billing info, posting the form causing the cart information to be lost.
I solved the problem by changing the markup in the erb file. The first code for the form was:
<form method="post" id="checkout" action="<%= url_for :action => :place_order %>" >
<%= submit_tag "Place Order" %>
</form>
This didn't work, so I tried the following:
<% form_tag :method => 'post', :controller => 'checkout', :action => 'place_order' do %>
<%= submit_tag 'Place Order 2' %>
<% end %>
Does anyone know why the second piece of code does not cause the cart information to be discarded?
I was going to write this as a comment, but it's too long
Helpers
As a rule, you generally need to use the Rails helpers (of which form_tag is one) wherever possible.
The reason being that as Rails (& HTML) develops, you'll find that the helpers will adapt to keep up with current syntax, whereas using "naked" HTML will not. This not only keeps your application conventional, but DRY
By manually typing out an HTML form, you not only open yourself up to syntax change issues, but also you won't get any of the benefits that Rails-integration provides, such as CSRF protection
form_tag
A quick note on your form_tag
You've defined the route for the form_tag by using :controller & :action. You'd be much better using one of the route_helpers that will be defined in your Rails routes file:
#config/routes.rb
resources :checkout, path_names: { create: "place_order" }
This will allow you to use the following:
<%= form_tag checkout_place_order_path do %>
It must also be noted that the form_for tag will actually employ the :post method by default
--
Params
You mention the params for your item are not being passed using your standard form.
The reason for this is actually quite simple - Rails builds a params hash whenever you send data to the controller via an HTML form.
The issue you have is that if you define your form with "naked" HTML, those params will not be generated correctly (they are built from your form element names). This means if you want to send the correct data through to your application, you'll be much better suited to using one of the helpers, such as form_for (which is what you've now discovered)
form_for
As mentioned by DMKE, you may wish to use form_for. This is different than form_tag, as it relies on having an ActiveRecord object to work with. You'd have to do it like this:
#app/controllers/checkout_controller.rb
Class CheckoutController < ApplicationController
def new
#checkout = Checkout.new
end
def create
#checkout = Checkout.new(checkout_params)
#checkout.save
end
end
You can then populate a form_for with the following:
#app/views/checkout/new.html.erb
<%= form_for #checkout do |f| %>
Rails usually adds CSRF protection token in form of hidden fields into your HTML form, but only if you use the Rails helper methods. Compare this view
<% form_tag method: 'post', controller: 'checkout', action: 'place_order' do %>
<%= submit_tag 'Place Order 2' %>
<% end %>
with this rendered output:
<form accept-charset="UTF-8" action="/checkout/place_order" method="post">
<div style="display:none">
<input name="utf8" type="hidden" value="✓">
<input name="authenticity_token" type="hidden" value="q5PYT8i+XTlnoKeVqCoz8VMtKKSJP+CXQb/E+G0Vxlk=">
</div>
<input type="submit" name="submit" value="Place Order 2">
</form>
Now, to get your orginal form up and running, you can either insert this snippet into your <form> tag:
<%= hidden_field request_forgery_protection_token, value: form_authenticity_token %>
or you can disable CSRF protection (not recommended at all!):
# in your app/controllers/application_controller.rb
skip_before_action :verify_authenticity_token
You should at least read the Rails Security Guide on why disabling the CSRF protection is a bad thing.
N.B. Is there a reason why you don't use form_for?

using html tags within ruby on rails if statement

i have a method in my application controller that checks whether a user is in the correct group to access certain functions.
My problem is that when a user edits their own account settings i dont want them to be able to edit their group, unless they are part of the transport group. Currently i have this
<%= if logged_in_as_transport? %>
<div class="field">
<%= f.label :user_type %><br />
<%= f.select :user_type, [['Transport','1'],['Staff','2']] %>
</div>
<% end %>
My method works fine as it is used to check the permissions on the page. It would be ideal if the drop down box was not visible for other groups but just being disabled would work too.
the above code creates a SyntaxError "unexpected tRPAREN"
');#output_buffer.append= ( if logged_in_as_transport? );#output_buffer.safe_concat('
if anyone can help that would be great.
<%= if logged_in_as_transport? %>
should be
<% if logged_in_as_transport? %>
an if statement's conditional doesn't have a return value to output to your view's HTML (which is what your'e saying you want to have happen by using <%= instead of <%)

Rails form multiple views?

I'm looking for a way to have a contact form in the application layout and show it on all pages.
Ideally i'd like to just do a
form_for #contact_us
I've tried creating the instance variable in the application controller but it doesnt seem to be in scope when the layout loads..
(does the layout load before the result of the action??)
I guess id settle for a form_tag.
Whats the ususal way of doing this kinda thing?
Thanks!
You can use a partial. Put the form code (use form_tag) in the partial and render the partial in the layout.
More about partials here.
What data are you assigning to #contact_us? You might consider using form_tag rather than form_for if your form doesn't require a resource.
Set up whatever you need in your application controller...
before_filter :prepare_contact_form
def prepare_contact_form
#contact_us = "The stuff your form needs"
end
Create a partial view containing your form. Assuming form_tag meets your needs, for lack of more information...
<!-- app/views/_contact_form.html.erb -->
<%= form_tag "/contact_us" do %>
<%= #contact_us %>
<%= text_field_tag :from_email %>
<%= text_field_tag :message %>
<%= submit_tag 'Submit' %>
<% end %>
Render the partial in your application layout...
<!-- app/views/layouts/application.html.erb -->
render :partial => "contact_form"
Then handle the request in whichever controller action /contact_us is routed to.