form_for was put inside fields_for - ruby-on-rails

I'm having a problem with form_for and fields_for.
So, my problem is:
I had a form_for, and inside this form_for, I use a fields_for. Inside this fields_for, I use a form_tag (i used ajax for this form_tag).
But when I view the generated HTML, it didn't display form_tag, it only display form_for. And I didn't understand why.
Please explain for me, why it didn't display form_tag.
Here is my form_for:
<div class="row">
<%= form_for #real_estate, url: admin_real_estate_update_path do |f| %>
<%= f.fields_for(:client) do |client| %>
<%= text_field :real_estate, :assessment_start_at, value: #real_estate.assessment_start_at %>
<%= render partial: "admin/real_estate/form/assessment", locals: {real_estate_id: #real_estate.id} %>
<% end %>
<%= f.submit "Submut", class: "btn btn-primary"%>
<% end %>
</div>
Here is my form_for which i put inside fields_for:
<%= form_tag admin_search_assessment_path(real_estate_id), method: :post, remote: true do %>
<%= text_field_tag :company_name, params[:company_name] %>
<%= submit_tag "Submit" %>
<% end %>
And i tried to add <form></form> follow as:
<div class="row">
<%= form_for #real_estate, url: admin_real_estate_update_path do |f| %>
<form></form>
<%= f.fields_for(:client) do |client| %>
<%= text_field :real_estate, :assessment_start_at, value: #real_estate.assessment_start_at %>
<%= render partial: "admin/real_estate/form/assessment", locals: {real_estate_id: #real_estate.id} %>
<% end %>
<%= f.submit "Submut", class: "btn btn-primary"%>
<% end %>
</div>
And form_tag was display, but form_for didn't display.
Update:
So, i used $("form_2").submit(function() {....}); to solve this problem.
Actually, i still want to use form-nested.

Inside this fields_for, I use a form_tag (i used ajax for this form_tag)
N'est pas possible, mon ami.
--
Here's how it works...
form_for and form_tag both generate pure HTML forms:
<form action="/action" method="POST">
</form>
Many people get confused about how Rails works - it's really quite simple. Rails employs "helper" methods to generate pure HTML which your browser can read.
Browsers only understand HTML/CSS at the moment. Thus, whenever you send a request to Rails - it has to return that data, otherwise a "web page" simply wouldn't be able to be processed.
Thus, when you ask whether you can nest forms, you have to abide by how the forms work in pure HTML (spec):
Note you are not allowed to nest FORM elements!
HTML fill-out forms can be used for questionaires, hotel reservations,
order forms, data entry and a wide variety of other applications. The
form is specified as part of an HTML document. The user fills in the
form and then submits it. The user agent then sends the form's
contents as designated by the FORM element. Typically, this is to an
HTTP server, but you can also email form contents for asynchronous
processing.
In short, it means that everything within a <form> tag is counted as a form by HTTP. This means that if you have another <form> tag, it's going to cause an error, preventing either from working.
You know this already (otherwise you wouldn't have mentioned ajax).
Your main problem is the use of <form></form> inside your current <form> object. This will confuse HTML profusely, and thus I would recommend replicating the submission of a form, without the <form> object itself:
#app/views/admin/real_estate/form/assessment.html.erb
<%= text_field_tag "[company_name]", params[:company_name], id: real_estate_id %>
<%= button_tag "Submit", type: "button" , data: { id: real_estate_id } %>
#app/assets/javascripts/application.js
$(document).on("click", "button", function(e){
e.preventDefault();
var real_estate_id = $(this).data("id");
$.ajax({
url: "path/to/real/estate/form/assessment/" + $(this).data("id")),
data: {company_name: $("input[type=text]#" + real_estate_id).val()}
success: function(data) {
//do something on success
},
error: function(data) {
//do something on error
}
});
});
This code will still output what you need.
The difference will be two-fold:
The user will experience the same functionality (the input will still be present)
The embedded form will be passed to the main "form" submit, but will not be passed through your strong params method (making it
invisible to your controller)
In effect, you're replicating the functionality of an HTML form through Ajax. Whilst I still wouldn't do it this way, it will give you the functionality you require.

Related

How do I pass a parameter to a form partial that is shown via CSS?

So my form partial is loaded in my div id="secondary", which is hidden on first page load.
When the user hits a button with a class called toggleSidebar, then the _form.html.erb is shown.
I have overridden the partial to display a new form (even if update is pressed) when a user is not logged in like this:
<%= simple_form_for(Post.new, html: {class: 'form-horizontal' }) do |f| %>
As opposed to the regular version that looks like this, and is included in an if statement on this same partial:
<% if current_user and current_user.has_any_role? :editor, :admin %>
<%= simple_form_for(#post, html: {class: 'form-horizontal' }) do |f| %>
The real issue is in my view, when someone goes to Update, this is what happens when the user is logged out:
<%= link_to "Update", "#", class: "togglesidebar" %>
This is perfect, it executes the CSS and shows the empty form partial perfectly.
However, when a user is logged in, I want it to send the parameter parent_id: #post with the execution of the sidebar being toggled.
This is how it looks with a normal new_post_path view (i.e. the non-sidebar new post view):
<% if current_user %>
<%= link_to "Update", new_post_path(parent_id: #post) %>
<% end %>
This is what my PostController#New looks like:
def new
#post = Post.new(parent_id: params[:parent_id])
end
How do I either pass the params in the regular non new_post_path version, or tackle this another way?
You could probably use a helper method.
Just browse to the 'helper' directory under 'app' folder and create a file similar to [name]_helper.rb
In this file create a module by [name]Helper and declare your helper method in this module.
This module is automatically required by rails.
A small example might help you.
The code in the link_helper.rb under app/helper directory
module LinkHelper
def populate_link(link1, link2, parameter)
if current_user
public_send(link2, parameter)
else
link1
end
end
end
The code in views is
<%= link_to 'update', populate_link('#', 'new_requirement_path',parameter: 33) %>
I'm a bit confused by the question, but I think you may be just need to use a hidden field to pass the parent_id param back?
e.g./
<%= simple_form_for(Post.new, html: {class: 'form-horizontal' }) do |f| %>
<%= f.hidden_field :parent_id, { value: #post.try(:id) } %>
<% end %>
HTH?
I am also a bit confused, but the following railscast might help you. It shows how to embed data in an html-tag. You can probably do it the same way.
railscast-> passing data to javascript
Out of the possibilities there I'd recommend the data-attribute:
<%= simple_form_for,(Post.new, html: {class: 'form-horizontal' }, **data: {post_id: #post.id}**) do |f| %>
<% end %>

Edit a post without leaving the page

I am trying to edit a micropost on the page without leaving the physical page.
In my app i have a page the renders all of a user's microposts using the partial below:
microposts/_micropost:
<%= render 'shared/edit_micropost', object: micropost %>
<%= micropost.title %>
<%= micropost.content %>
<%= micropost.url %>
<%= raw "Tags: #{micropost.tag_list.map {|t| link_to t.capitalize, tag_path(t)}}" %>
shared/edit_micropost:
<%= link_to "edit", object, remote: true %>
<%= form_for object do |object| %>
<%= object.text_field :title %>
<%= object.text_area :content %>
<%= object.text_field :url %>
<%= object.text_field :tag_list %>
<%= object.submit "Update", class: "btn btn-mini" %>
<% end %>
When I click "edit" I would like the form to come up so that the title, content, url, and tag_list of the specific micropost is editable.
Right now when I click "edit" I get No route matches [GET] "/microposts/452" I'm not sure how to specify a working path in my link_to. I assume I have to move the form_for to a JS file?
I'm new to programming and would really appreciate some help, thanks.
There is a gem maybe you want to try it, 'Best in Place' is a jQuery based AJAX Inplace-Editor
Also there is a screencast for it by Ryan Bates
A straightforward way to do this would be to go ahead and render the form on the page, but hide it with javascript. Then when the user clicks the button, show it again. This way the form is also available to users that don't have js enabled.
Then it's just a matter of setting the remote: true option in the form to get it to submit via ajax and use an ajax callback to notify the user of success or failure (if you want). Again, this approach will still allow non-js users to submit the form with a normal request, while users with js enabled will get the slick ajax functionality.

Submit a form after an event. Rails

Here is the part of code I am working on.
<td class= "block" id=<%= dom_id(Block.find(block.id)) %> colspan=2>
<%= form_for block do |f| %>
<%= f.text_area :content, :size => "5x4" %>
<%= f.hidden_field :id_case %>
<%= f.hidden_field :canvas_id %>
<%= f.submit "Submit", class: "save" %>
<% end %>
</td>
I would like to add another form under this one, still in the "td". And I would like this one to be submitted when I drag a special element in the (which is droppable)
I figured out that forms can have the data-remote attribut, but I didn't really get how we have to use it. Is this attribute made for execute javascript after we've submitted the form or is it a helper that submits the form after a special element ?
If this is the second case, it really fits with my idea but I really didn't understand how to use it.
Thanks for your help
I am not sure exactly what you want to know here, but a form with data-remote="true" means that it will be submitted by Ajax rather than a 'normal' submit. You can add remote: true to your form like this:
<%= form_for(#post, remote: true) do |f| %>
...
<% end %>
The resulting form will have a data-remote="true".
To submit a form by Ajax after you have dropped your element you can do the following using jQuery:
$("#your-droppable-element").droppable({
drop: function( event, ui ) {
$('#your-form').submit();
}
});
I hope that helped :)

edit form submitting to the wrong url and remote: true failing to be picked-up

This has been driving me nuts because it doesnt seem to make any sense.
I want to do something relatively simple.
Display an edit form in a modal on the index page.
I have the following code looping through a collection of sites
<%= render(#sites) %>
<%= will_paginate #sites %>
Within the sites partial i have the following form hidden away
<%= simple_form_for site, remote: true do |f| %>
<%= f.input :name %>
<%= f.input :matter %>
<%= f.submit "Save", :class => "button gr thirt", id: "site_save" %>
<% end %>
instead of generating the expected HTML i get the following, linking to the show action, am I missing something fundamental here?
<form accept-charset="UTF-8" action="/sites/1" class="simple_form edit_site" data-remote="true" method="post" novalidate="novalidate">
</form>
I was looping through a collection of #sites, a results returned by a call to Site.all
so the object being served to the above form is one of the |site|'s contained within #sites
If you serve a form_for form with a an object retrieved from the database or a 'new record' object like Site.new, it will automatically differentiate and modify the route etc accordingly between the create and the update action.
The site object contained in the #sites block was not recognizable by the form_for. So a quick re factor to request an edit from via ajax, and provide the form with the instance variable created by the edit action (#site = Site.find(params[:id]) ) was recognizable by the form_for helper and meant that the submit action, accordingly adjusted to the correct route.

Rails 3 submit form with link

How I can submit form with link on correct rails 3 format?
Thanks.
<%= form_for #post do |f| %>
<%= f.label :title %><br>
<%= f.text_field :title %>
<p><%= f.submit %></p>
<% end %>
My code sample.
For people who came here via Google, I have an improvement on Zequez's answer. Instead of the method that he gives, add this method to the application helper instead:
def link_to_submit(*args, &block)
link_to_function (block_given? ? capture(&block) : args[0]), "$(this).closest('form').submit()", args.extract_options!
end
Then, as Zequez stated, for simple links you can just do this in your view:
<%= link_to_submit 'Submit Form' %>
...and for more complicated buttons you can pass HTML options and a block to be used inside the link. If you use Twitter Bootstrap, for example, this lets you add CSS classes, formatting and icons:
<%= link_to_submit( class: 'btn btn-primary' ) do %>
<strong>Submit</strong> the Form <i class="icon-arrow-right"></i>
<% end %>
The JQuery code will work as long as the link is a child of the form (that is, as long as link_to_submit is called from somewhere within the form_for block).
"Correct" is a tricky word in this context ;) . One could ask why you're not just taking a button element and make it look like a link?
Anyways — you can't achieve this with plain HTML (at least not to my knowledge). With a Javascript framework like e.g. jQuery you could simply do something like this:
$('a').click(function(){
$('form').submit();
return false;
});
Rails 2.3.x had a link_to_remote helper which let's you specify a :submit parameter (= DOM element's ID, default is the parent form). So you were be able to write:
link_to_remote 'submit', :url => {…}, :submit => "my_form"
But with Rails 3's push to UJS, this helper is gone.
You can add the following to the application helper:
def link_to_submit(text)
link_to_function text, "$(this).closest('form').submit()"
end
Then inside your view files you can just call
link_to_submit 'Submit Form'
And the link must be child of the form.
With jquery, this one-liner will work fine for a simple form.
<%= link_to t("translate.submit"), "#", class: "make it beautiful", :onclick=>"$('form').submit()" %>
Of course you don't really have to use jquery, just finding the dom element for your form will work fine as well.
<%= link_to t("translate.submit"), "#", class: "make it beautiful", :onclick=>"document.getElementById('your_form_id').submit()" %>
This way you don't use any ajax, just plain form submit.
In Rails 3, the link_to_remote helper is gone, but it's replaced with
link_to 'submit me', url_for(#post), {:remote => true, :class => 'submit_me'}
In your case, you likely want your form to do the AJAX, like so:
<%= form_for #post, :remote => true do |f| %>
<%= f.label :title %><br>
<%= f.text_field :title %>
<p><%= f.submit %></p>
<% end %>
With a companion link:
link_to 'submit me', '#', :class => 'submit_me'
Then, in an .js file included in the page body:
$('.submit_me').click(function() {
$('form').submit();
return false;
});
The idea is that anything more complicated than turning a link or form into an ajax request should be done with the jQuery callbacks, as listed here:
https://github.com/rails/jquery-ujs/wiki/ajax
And if you want to really get into interactive AJAX requests, go here for a great 2-part article on it.

Resources