Updating partial after submit - ruby-on-rails

On my comments show page I am loading a partial called '_links' and the form to add a new link like this.
comments/show.html.erb
<%= render :partial => 'comments/newlink', locals: {question:question} %>
<%= render :partial => 'links/form', locals: {question:question} %>
comments/_newlink
<% question.links.each do |link| %>
<%= link.body %>
<% end %>
The form looks like this.
links/_form.html.erb
<%= simple_form_for [question, Link.new] do |f| %>
<%= f.input :body %>
<%= f.button :submit, class: "button" %>
<% end %>
I then have a file 'link.js.erb':
comments/link.js.erb
$('.button').append('<%= j (render :partial => 'comments/newlink') %>');
What I am trying to do is update the _links partial using jquery after someone clicks the submit button but it's not quite working. I believe the jquery is correct and it's a rails issue with where I placed the partials.

There are couple of things which you are missing
a. You need to submit your form by ajax so use remote: true option. Your form should be like this:
<%= simple_form_for [question, Link.new], remote: true do |f| %>
<%= f.input :body %>
<%= f.button :submit, class: "button" %>
<% end %>
b. Your form will send a request to create method in your links controller so your method should be like this:
def create
#link = Link.new(link_params)
#question = Question.find(params[:question_id])
respond_to do |format|
if #link.save
format.js # this will look for a file names create.js.erb in views/links directory
else
render "new"
end
end
c. Render your partial and pass locals to it in create.js.erb:
$('.button').append("<%= j (render :partial => 'comments/newlink', locals: {question: #question}) %>"); #notice using double qoutes not single
For details you should checkout Working with Javascript in Rails
Update:
<div id="link">
<%= render :partial => 'comments/newlink', locals: {question:question} %>
</div>
<div id="link-form">
<%= render :partial => 'links/form', locals: {question:question} %>
</div>
and then to update your partials use this js in create.js.erb
$('#link').html("<%= j (render :partial => 'comments/newlink', locals: {question: #question}) %>"); #notice using double qoutes not single
$('#link-form').html("<%= j (render :partial => 'links/form', locals: {question: #question}) %>"); #notice using double qoutes not single

Related

How to call a form from an element

I have Post with nested elements who also have different nested form (text for this example) according to a :cat variable.
To create the texts I'm using a post method create_element with a variable (cat = 1). And I would like to call an AJAX method to render the new text created into my post form.
My problem: I don't know how to call the text nested_form created directly into my AJAX method.
My code :
Post form (posts/new):
<%= simple_form_for #post do |f| %>
<div class="elements">
<%= f.fields_for :elements do |element| %>
<%= render 'posts/element_field', f: element %>
<% end %>
</div>
<div class="btn_add_element_area">
<a href="/posts/<%=#post.id%>/create_element?cat=1" data-method="patch" data-remote="true">
<i class="fa fa-font"></i>
</a>
</div>
<%= f.submit "Publish", class: "btn" %>
<% end %>
Post form (posts/_element_field):
<div class="element_form" id="element_form<%= f.object.id %>">
<div class="undisplay">
<%= f.number_field :cat %>
</div>
<%- if f.object.cat == 1 %>
<%= f.fields_for :post_texts do |text| %>
<%= render 'posts/elements/text_field', f: text %>
<% end %>
<% end %>
</div>
Post form (posts/_text_field):
<%= f.text_area :content %>
Post controller (create_element) :
def create_element
if params[:cat] == "1"
#element = Element.create(post: #post, cat: 1)
Text.create(element: #element)
end
respond_to do |format|
format.js {render 'elements/create'}
end
end
And the AJAX method (elements/create) :
$('.elements').append("<%= j render partial: 'posts/element_field', locals: {f: #element} %>");
Error = undefined method `object'
The problem is that in the AJAX file I call the #element created for my f variable instead of calling the form of this #element.
I also tried something like that for the AJAX method, but still not working :
<% form_for(#element) do |elm| %>
$('.elements').append("<%= j render partial: 'posts/element_field', locals: {f: elm} %>");
<% end %>
Error = undefined method `element_path'
Or
<%= simple_form_for(#post) do |p| %>
<%= p.fields_for :elements, #element do |elm| %>
$('.elements').append("<%= j render partial: 'posts/element_field', locals: {f: elm} %>");
<% end %>
<% end %>
No error but nothing happen
If you have any ideas to solve that, I would really appreciate !
PS: And ideas to improve the question title are welcome !!

Rails: How to pass a url path to a form_for partial in Rails?

I'm trying to pass a url and variable to a form partial in Rails.
Method #1:
This works, but I'd rather not hardcode post_create_path into the form, so that it can be used for #update as well.
new.html.erb
<%= render partial: 'shared/form', locals: { form: #form } %>
_form.html.erb
<%= form_for form, url: post_create_path do |f| %>
...
<% end %>
Method #2:
This does not work.
new.html.erb
<%= render partial: 'shared/form', locals: { form: #form, url: post_create_path } %>
_form.html.erb
<%= form_for form, url: url do |f| %>
...
<% end %>
Error:
undefined local variable or method `url' for #<#:0x007f8d4d831fd0>
What I've also tried:
Just url instead of url:url but getting the same error.
Following this thread: How to pass url to partial/form?
I've been trying to make this work for a couple hours now and feel like I'm running out of options to try. Any help in pointing out what I'm doing wrong would be super appreciated!
you can use different actions by opening form_for on edit and new view templates and then pass the form object to the partial which contains all the fields of the form that are common to both create and update
new.html.erb
<%= form_for #post, :url => { :action => "create" } do |form| %>
<%= render partial: 'shared/form', locals: { f: form } %>
edit.html.erb
<%= form_for #post, :url => { :action => "update" } do |form| %>
<%= render partial: 'shared/form', locals: { f: form } %>
shared/_form.html.erb
<%= f.text_field :title %>
...
<%= f.submit "Save" %>
<% end %>
Use the locals hash as a form_for argument:
# new.html.erb
<%= render partial: 'shared/form', form: #form, locals: { url: post_create_path, method: :post} %>
# edit.html.erb
<%= render partial: 'shared/form', form: #form, locals: { url: post_update_path, method: :put} %>
# _form.html.erb
<%= form_for form, locals do |f| %>
...
<% end %>
locals is just a hash and you can give it any name (like vars). Then use it consistently in the views and the form.
I had the same challenge when working on a Rails application with namespaced routes, but sa77's answer helped me.
Just to add to it.
My routes file is like this:
Rails.application.routes.draw do
namespace :users do
resources :students
end
end
So my new.html.erb was modified like this:
<h1>New User</h1>
<%= form_with(model: #user, url: users_students_path, local: true) do |form| %>
<%= render partial: 'form', user: #user, locals: { form: form } %>
<% end %>
<%= link_to 'Back', users_students_path %>
And my edit.html.erb was modified like this:
<h1>Editing User</h1>
<%= form_with(model: #user, url: users_student_path(#user), local: true) do |form| %>
<%= render partial: 'form', user: #user, locals: { form: form } %>
<% end %>
<%= link_to 'Show', users_student_path %> |
<%= link_to 'Back', users_students_path %>
And then my _form.html.erb file was modified like this:
<div class="field">
<%= form.label :email %>
<%= form.text_field :email %>
</div>
<div class="field">
<%= form.label :password %>
<%= form.text_field :password %>
</div>
<div class="actions">
<%= form.submit %>
</div>
That's all.
I hope this helps

passing variable to simple form symbol

this is my _form_item partial in which I used symbol :order_item
<%= simple_form_for :order_item do |f| %>
.....
<% end %>
here is my view in which I want to render that partial:
<%= content_tag_for :tr , #order.order_items do |i| %>
<div class="hide">
<%= render :partial => "form_item" %>
</div>
<% end %>
How can I pass "i" object to :order_item?
UPDATE:
I prefer to keep it ":order_item" instead of changing it to something like "foo".
You should have:
<%= render partial: 'form_item', locals: {order_item: i} %>
or a shorthand:
<%= render 'form_item', order_item: i %>
And in your form_item partial you should have:
<%= simple_form_for order_item do |f| %>
...
Just do
<%= simple_form_for item do |f| %>
.
.
<% end %>
and render the partial via
<%= render :partial => 'form_item', :locals => { :item => i } %>
You can pass i as a locals to the partial like follows:
<%= render :partial => "form_item", :i => i %>
and you'll have i available in the _form_item partial.
Update:
Local variables passed to partials are variables and not symbols. You could keep the name order_item like follows:
<%= render :partial => "form_item", :order_item => i %>
And update your order_item partial as follows:
<%= simple_form_for order_item do |f| %>
.....
<% end %>
I think I understand why you do not want to change :order_item to just order_item. I think you are going to have to update your other calls to pass in local variable order_item where ever you are making a call to this partial.

Rails - AJAX/JQuery not working

For my application, I have projects where users can make comment (class Newcomments) postings. Right now it posts great but on page refresh. I am trying to use AJAX/JQUERY so that it will post with no page refresh. I am following this railscasts tutorial.
So right now, the posts are made to my database and the page does not refresh. But when I refresh, the posts shows up. The page that I render my comments for a specific project is on the projects/_comments.html.erb.
Question: How would I adjust it so that it the new comment made renders?
newcomments_controller.rb
def create
#newcomment = #commentable.newcomments.new(params[:newcomment])
if #newcomment.save
respond_to do |format|
format.html { redirect_to comments_project_path(#commentable) }
format.js
end
else
render :new
end
end
view/newcomments/_form.html.erb
<span class="comment">
<%= form_for [#commentable, #newcomment], remote: true do |f| %>
<%= f.text_area :content, rows: 3, :class => "span8" %>
<%= f.hidden_field :user_id, :value => current_user.id %>
<%= f.submit "Add Comment", :class => "btn btn-header" %>
<% end %>
</span>
view/newcomments/create.js.erb
$('#newcomment').append('<%= j render(#newcomments) %>');
projects_controller.rb
def comments
#commentable = #project
#newcomments = #commentable.newcomments.newest.page(params[:comments_page]).per_page(10)
#newcomment = Newcomment.new
respond_to do |format|
format.html # show.html.erb
format.json { render json: #project.comments }
end
end
projects/comments.html.erb
<%= render 'comments' %>
projects/_comments.html.erb
<%= render #newcomments %>
view/newcomments/_newcomment.html.erb
<div class="comments">
<%= link_to newcomment.user.name %></strong>
Posted <%= time_ago_in_words(newcomment.created_at) %> ago
<%= newcomment.content %>
</div>
<span class="comment">
<%= form_for [#commentable, #newcomment] do |f| %>
<div class="field">
<%= f.text_area :content, rows: 3, :class => "span8" %>
</div>
<%= f.hidden_field :user_id, :value => current_user.id %>
<div class="actions">
<%= f.submit "Add Comment", :class => "btn btn-header" %>
</div>
<% end %>
<% unless newcomment.newcomments.empty? %>
<%= render #newcomments %>
<% end %>
</span>
Try binding AJAX actions as described here:
http://www.alfajango.com/blog/rails-3-remote-links-and-forms/
Also, consider returning a render comments partial html instead of json comment object, to do so you need to tell in form after :remote directive that :'data-type'=>'html', so that returned html will hit function binded on AJAX success, and then swap html of container div with, for example, jQuery

Rails partial not rendering through ajax call

I am trying to render a partial through ajax when a user clicks on button destroying a relationship between two products. The destroy action works, but I can not get the rendering of the partial to work.
The partial is rendered on the edit page for a product:
edit.html.erb
<div id="relationship_form">
<%= render "relationships", product: #product %>
</div>
_relationships.html.erb
<%= render "unrelate", relationship: relationship %>
_unrelate.html.erb
<%= form_for(relationship,html: { method: :delete },remote: true) do |f| %>
<%= f.submit "Remove", class: "btn btn-small" %>
<% end %>
relationships_controller.html.erb
def destroy
...
respond_to do |format|
format.html { redirect_to edit_product_path }
format.js
end
end
destroy.js.erb
$("#relationship_form").html("<%= escape_javascript(render :partial => 'products/relationships', :locals => {:product => #product}) %>");
I have checked that the ajax call goes through to the destroy.js.erb, by inserting an alert, so there must be an error in the javascript?
Update:
I got it to work by moving the form in the _unrelate partial to the _relationship partial. Still not really clear why it made it work.
_relationships.html.erb
<%= form_for(relationship,html: { method: :delete },remote: true) do |f| %>
<%= f.submit "Remove", class: "btn btn-small" %>
<% end %>

Resources