can't refresh a rails html div with ajax - ruby-on-rails

the following renders "2" in the div as it should when a form is submitted.
full brands/create.js.erb version 1:
$("#brand_ajax").html("1")
$("#brand_ajax").html("0")
$("#brand_ajax").html("2")
partial brands/show_brands.html.erb
The div I want to refresh
<% for brand in #brands%>
ID: <%= h brand.id %>
<% end %>
partial cars/show.html.erb
The ajax call
<%= form_for([#car, #car.brands.build], **remote: true**) do |f| %>
<%= f.fields_for :brandsdo |a| %>
<%= a.text_field :name, placeholder: "New Manufacturer" %>
<% end %>
<%= f.submit "+", class: "btn inline" %>
<% end %>
**/*The div I want to refresh*/**
<div id="brand_ajax">
<%= render 'brands/show_brands' %>
</div>
The brands controller
respond_to do |format|
if #brand.save
format.html { redirect_to #car }
format.js
else
flash[:notice] = "Error!"
format.html { redirect_to #car }
end
end
the following does not render "2" after submitting a new brands form - does not refresh at all. just shows the old version of
'show_brands'.
full brands/create.js.erb (to illustrate)
$("#brand_ajax").html("1")
$("#brand_ajax").html("<%= escape_javascript render 'show_brands' %>")
$("#brand_ajax").html("2")
any ideas why such a thing should happen?

Try
$("#brand_ajax").html("<%= j render :partial => 'show_brands' %>")

Related

Link_to remote:true not rendering a partial

Trying to get a flash message and render a partial on an ajax call with link_to and remote:true
I have in my controller examples.rb:
def create
* Some stuff happens *
respond_to do |format|
format.js
format.html do
flash[:notice] = "Works!"
redirect_back(fallback_location: root_path)
end
end
end
I have the "link_to" form in _one_partial.html.erb
<%= link_to examples_path(whatever: locals[:whatever]), class: "whatever", method: :post, remote: true do %>
<div class="whatever_vix">
<p> Click Here! </p>
</div>
<% end %>
which is in a view as:
<div id="addhere">
<%= render 'favorites/one_partial', locals: {whatever: #whatever} %>
</div>
and in create.js.erb
$('#addhere').append("<%= j render 'whatever/another_partial' %>")
The ** some stuff happens ** part in my controller obviously works, but the new partial in create.js.erb doesn't show, neither the flash message appears once I add remote:true to the "link_to" form

Rails partial not refreshing with create action

I realize there are dozens of similar questions here on this topic, I have looked through many of them and tried to duplicate the solutions and nothing has worked for me.
I have a list of tasks displayed in the index view as a partial, when the user adds a task I would like list to show the newest task (as well as all the others already there).
Here is the create controller:
def create
#task = current_user.tasks.build(task_params)
if #task.save
flash[:success] = "Task added"
respond_to do |format|
format.js
end
else
flash[:error] = "Task not added"
render 'new'
end
The _new partial:
<%= form_for(#task, method: :post, remote: true) do |f| %>
<%= f.label :comments %>
<%= f.text_field :comments, id: "task-comments" %>
<%= f.submit "Insert" %>
<% end %>
Index.html.erb
<div id="new-task-form">
<%= render 'new' %>
</div>
<div id="current-tasks">
<%= render partial: 'show_list', locals: {tasks: #tasks} %>
</div>
create.js.erb
console.log("create.js.erb called");
document.getElementById("task-comments").value = "";
document.getElementById("current-tasks").html('<%= j(render partial: "show_list") %>');
I have been able to get the console to log the message and even been able to clear the input box but the partial does not render, I have tried this in a few different ways and the script always seems to stop executing when it gets to the escape javascript line.
There are no JS errors, as stated above, the console logs the message when the "submit" button is pressed. There is a warning [Violation] Forced reflow while executing JavaScript took 114ms but I don't think that is relevant to this issue.
Here is the partial that I am trying to render _show_list.html.erb
<% unless #tasks.nil? %>
<ul>
<% tasks.each do |tsk| %>
<li><%= tsk.comments %></li>
<% end %>
</ul>
<% end %>
def create
#task = current_user.tasks.build(task_params)
if #task.save
flash[:success] = "Task added"
#respond_to do |format|
#format.js
#end
else
flash[:error] = "Task not added"
render 'new'
end
end
It's always good practice to use local variable in partial
1) => Index.html.erb
<div id="new-task-form">
<%= render 'new' %>
</div>
<div id="current-tasks">
<%= render partial: 'show_list', locals: {tasks: #tasks} %>
</div>
2) => If you are using jquery (create.js.erb)
console.log("create.js.erb called");
$("#task-comments").val('');
$("#current-tasks").html('<%= j render "show_list", tasks: #tasks) %>');
3) => _show_list.html.erb(Use tasks instead of #tasks)
<% unless tasks.blank? %>
<ul>
<% tasks.each do |tsk| %>
<li><%= tsk.comments %></li>
<% end %>
</ul>
<% end %>
ok you have some problem here with your validation on the show_list partial.
you have this line
<% unless #tasks.nil? %>
try to use something more readable like
<% if #tasks.present? %>
and on your controller create action, you don't fill the #tasks variable, so that's the problem in reality, add on you controller the load for all the tasks after saving the new one.
if #task.save
#tasks = Task.all
flash[:success] = "Task added"
and that will make it work, but I recommend to load just the created one and add just one column to the table and not update the complete list again if you have all the others on the client already.

Rails 4 - Combine Params from Previous Page (Pass Array in Hidden Field?)

On Rails 4. I'm working on an e-commerce app where a user can choose to go through a wizard-like process.
First the user selects a color scheme,
then selects products from two different pages,
then the results of those product selections are displayed on a fourth page.
No rows are created or updated in the database, I just want the results to be displayed on the fourth page (because this info is then fed to a third-party service).
Because the array would be no more than five or six choices, I am passing the product ids through the URL params. Here's the controller (let's say on the second page the user selects paper products and on the third page the user selects pencil products)
class WizardController < ApplicationController
def index
# Where the user clicks on a color scheme link
end
def paper
#color = ColorScheme.find(params[:color_scheme_id])
#product = Product.all
end
def paper_submit
respond_to do |format|
format.html { redirect_to wizard_pencils_path(
color_scheme_id: params[:color_scheme][:color_scheme_id],
id: params[:ids]) }
end
end
def pencils
#color = ColorScheme.find(params[:color_scheme_id])
#product = Product.all
#paper = Product.find(params[:id])
end
def pencils_submit
respond_to do |format|
format.html { redirect_to wizard_finish_path(
color_scheme_id: params[:color_scheme][:color_scheme_id],
id: params[:ids] + [:paper_ids]) } # ?? Not sure what goes here
end
end
def finish
# Haven't gotten here yet
end
private
def color_scheme_params
params.require(:wizard).permit(:color_scheme_id, :id)
# Also not too sure about this area either
end
end
Routes:
get '/wizard/paper', controller: 'wizard', action: 'paper'
put '/wizard/paper', controller: 'wizard', action: 'paper_submit'
get '/wizard/pencils', controller: 'wizard', action: 'pencils'
put 'wizard/pencils', controller: 'wizard', action: 'pencils_submit'
get '/wizard/finish', controller: 'wizard', action: 'finish'
resources :wizard
Form for the second page (selecting paper products)
<%= form_for([#color], html: {multipart: true}, url: {action: "paper_submit"}, method: 'put') do |f| %>
<%= f.hidden_field(:color_scheme_id, value: #color.id) %>
<div class="row">
<% #product.where(enabled: true, color_scheme_id: #color).each do |product| %>
<% if product.tags.where(name: "Paper").count > 0 %>
<div class="col-lg-3 col-md-4 col-sm-6">
<%= check_box_tag 'ids[]', product.id -%>
<%= link_to image_tag(product.thumbnail.url(:thumbnail_small_opt), alt: product.name), product %>
<p><%= link_to product.name, product %>, $<%= product.price %></p>
</div>
<% end %>
<% end %>
</div>
<div class="row">
<div class="col-lg-12">
<p style="text-align:right;"><%= f.submit "Next: Select Pencils", class: "btn bg-primary" %></p>
</div>
</div>
<% end %>
So far this all works fine. But, the problem is when the user makes product selections on the third page and reaches the fourth page. Ideally I want my application to combine the product id params from the second page with the different product ids from the third page.
<%= form_for([#color], html: {multipart: true}, url: {action: "embellishments_submit"}, method: 'put') do |f| %>
<%= f.hidden_field(:color_scheme_id, value: #color.id) %>
<!-- A hidden field maybe?? This does not work though -->
<%= f.hidden_field(:paper_ids, multiple: true, value: #paper) %>
<div class="row">
<% #product.where(enabled: true, color_scheme_id: #color).each do |product| %>
<% if product.tags.where(name: "Pencil").count > 0 %>
<div class="col-lg-3 col-md-4 col-sm-6">
<%= check_box_tag 'ids[]', product.id -%>
<%= link_to image_tag(product.thumbnail.url(:thumbnail_small_opt), alt: product.name), product %>
<p><%= link_to product.name, product %>, $<%= product.price %></p>
</div>
<% end %>
<% end %>
</div>
<div class="row">
<div class="col-lg-12">
<p style="text-align:right;"><%= f.submit "Next: Purchase Your Selections", class: "btn bg-primary" %></p>
</div>
</div>
<% end %>
It seems like a simple thing, I just want to combine an array from two different pages from the URL params but I can't figure out how to do this. Don't really want to use a gem for this because this is all I need to figure out. Thanks for any help.
Just put your variables into session:
def paper_submit
session[:paper_ids] = params[:ids]
respond_to do |format|
format.html { redirect_to wizard_pencils_path(
color_scheme_id: params[:color_scheme][:color_scheme_id]
) }
end
end
def pencils
#color = ColorScheme.find(params[:color_scheme_id])
#product = Product.all
#paper = Product.find(params[:id])
end
def pencils_submit
session[:pencil_ids] = params[:ids]
respond_to do |format|
format.html { redirect_to wizard_finish_path(
color_scheme_id: params[:color_scheme][:color_scheme_id]
) }
end
end
def finish
#all_products = Product.where(
enabled: true,
color_scheme_id: params[:color_scheme_id],
id: session[:paper_ids] + session[:pencil_ids]
)
end
finish.html.erb:
<% #all_products.each do |product| %>
<%= product.name %>
<br />
<% end %>
You should add those two arrays and make something like:
def pencils_submit
respond_to do |format|
format.html { redirect_to wizard_finish_path(
color_scheme_id: params[:color_scheme][:color_scheme_id],
product_ids: params[:ids] + [:paper_ids]) }
end
end
Then in your form:
<% #product_ids.each do |id| %>
<%= f.hidden_field_tag 'product_ids[]', id %>
<% end %>
Then in your last finish action do whatever you want.

Displaying record count - Ruby on Rails - Ajax

I am new to rails so sorry if sometimes I don't make much sense. Here is what I am trying to do. I am trying to build a vote system. So next to a blog post there is a link that says 'vote' (will probably say like later). So far I have working: when the vote button is clicked, a value of '1' is delivered to the vote table and then that particular posts vote records display beneath the vote via AJAX (I copied a comment functionality). Instead of rendering all the number '1's below, I want it to render the updated count.
My vote table has the columns 'vote' and 'post_id' that are successfully being entered. My thinking was that I could just change my partial template to do this. Here is the code:
votes_controller:
class VotesController < ApplicationController
def create
#post = Post.find(params[:post_id])
#vote = #post.votes.create!(params[:vote])
respond_to do |format|
format.html { redirect_to #post}
format.js
end
end
end
def count
#post = Post.find(params[:post_id])
#vote = calculate :count
respond_to do |format|
format.html { redirect_to #post}
format.js
end
end
end
Here is the page where is is showing, /posts/show.html.erb:
<div id="backto"<%= link_to 'Back to all BattleCries', posts_path %></div>
<%= render :partial => #post %><br/>
<p5>Add a Comment</p5>
<div id="belt">
<div id="belttext">
<% remote_form_for [#post, Comment.new] do |f| %>
<p>
<%= f.text_area ( :body, :class => "commentarea") %>
</p>
<%= f.submit "Add Comment"%>
<% end %>
</div>
<div id="beltbottom">
</div>
</div><br/>
<br/><p5>Comment Stream </p5>
<div id="comments">
<%= render :partial => #post.comments %>
</div>
<p>
<% remote_form_for [#post, Vote.new] do |f| %>
<p>
<%= f.hidden_field :vote, :value => '1' %>
</p>
<%= f.submit "Vote" %>
<% end %>
<div id="vote">
<div id="votes">
<%= render :partial => #post.votes %>
</div>
</div>
</p>
Here is the :partial, /votes/_vote.html.erb: (this is where I thought I would just need to change it to vote.count, or post.count or something but can't get it to work).
<% div_for vote do %>
<%= h(vote.vote) %>
<% end %>
Here is the /votes/create.js.rjs file:
page.insert_html :bottom, :votes, :partial => #vote
page[#vote].visual_effect :highlight
I hope that all makes sense.
I think it's repeating because your .rjs is "inserting at the bottom" of the div instead of "replacing" ... you probably want page.replace_html
It would be better to have a DIV or SPAN tag that contains the number of votes for a post ... then have your .rjs file update the DIV's inner_html with the number of votes (which would be #post.votes.count) ... I don't think you really need a partial.
You probably want:
<%= #post.votes.count %>
You also probably want to use replace instead of insert_html - does that make sense? Insert is just adding more elements to the DOM whereas replace will replace the element.

Ruby on Rails: Deleting a post with Ajax in navigation and showing the following

Thanks for reading!
So I'm relatively new to RoR (Rails 5) and I try to render posts of a user in a partial (_posts_panel.html.erb) which contains another partial: the navigation (_posts_navigation.html.erb). I'm using ajax to show the posts when clicked on in the navigation which is working fine.
Now I want to use it for deleting a post. The post is destroyed when I click on the button and I managed to remove it in navigation.
What is not working:
the next post should be shown in the panel after the deletion
when there is no post left I want to reload the panel because another partial (_posts_empty.html.erb) should be rendered
My Code:
_posts_panel.html.erb: (it is rendered in show.html.erb of user)
<% if #user.simple_posts.empty? %>
<%= render 'simple_posts/shared/posts_empty' %>
<% else %>
<div id="post-navigation">
<%= render 'simple_posts/shared/posts_navigation' %>
</div>
<%= simple_posts_edit_button(current_user, #simple_post)%>
<%= simple_posts_delete_button(current_user, #simple_post)%> #button helper
<div id="show_post">
<%= render #simple_post %>
<%= yield %>
</div>
<%end %>
_posts_navigation.html.erb
<div class="bootstrap-vertical-nav">
<ul class="nav flex-column">
<% #user.simple_posts.reverse_each do |post|%>
<li class="nav-item" id="<%= #simple_post.id %>">
<%= link_to post.title, user_simple_post_path(#user, post), remote: true, class:"nav-link text-dark" %>
</li>
<% end %>
</ul>
</div>
<% if #user.id == current_user.id %>
<%= link_to "+ New Post", new_user_simple_post_path(current_user), class: "btn btn-info w-100", role: "button" %>
<% end %>
destroy.js.erb
$('li#<%= #simple_post.id %>').remove();
simple_posts_controller.rb
def destroy
#simple_post.destroy
#simple_post =current_user.simple_posts.first
respond_to do |format|
# format.html { redirect_to simple_posts_url, notice: 'Simple post was successfully destroyed.' }
format.js
end
end
I tried to append in destroy.js.erb the same code from showing the post $('#show_post').html("<%= escape_javascript render #simple_post %>"); but it's not working correctly. When deleting the first post (but only that one) the next one is shown but the post is not removed from the navigation. I also tried $('#post-navigation').html("<%= escape_javascript render partial: 'simple_posts/shared/posts_navigation' %>"); and it nothing happens.
Also I tried to reload the whole panel with $('#post-panel').html("<%= escape_javascript render partial: 'simple_posts/shared/posts_panel' %>");in show.html.erb of user but again: nothing. I'm not sure if I have to specify in which view or partial exactly it has to render the partial.
I don't really know how to approach this further.
Edit 1
ButtonHelper.rb
def simple_posts_delete_button(current_user, simple_post)
if(current_user.id == #user.id)
link_to svg('x-square'), [current_user, simple_post], remote: true, method: :delete, class:"btn"
end
end
Edit 2
show-action from simple_posts_controller.rb
def show
#user = User.find{params[:id]}
#simple_post = SimplePost.find(params[:id])
respond_to do |format|
format.js
format.html # show.html.erb
end
end
show.js.erb
$('#post-actions').html("<%= j render partial: 'simple_posts/shared/posts_actions', locals: {simple_post: #simple_post, user: #user} %>");
$('#show-post').html("<%= j render #simple_post %>");
There are several problems with your partials:
First, to remove the post from your navigation you just need to update the partial, the post is already destroyed/removed at this point.
After destroy, #simple_post in your button helper is not updated with ajax and still comes from the users_controller (where you set it the first time i presume)
You can put your action buttons inside a new partial and specify the locals.
You can also wrap the html inside a main div for the last update (when all the posts are deleted)
_posts_panel.html.erb:
<div id="panel">
<% if #user.simple_posts.empty? %>
<%= render 'simple_posts/shared/posts_empty' %>
<% else %>
<div id="post-navigation">
<%= render partial: 'simple_posts/shared/posts_navigation', locals: { simple_post: #simple_post } %>
</div>
<div id="post-actions"> #<-- new partial
<%= render partial: 'simple_posts/shared/posts_actions', locals: { simple_post: #simple_post } %>
</div>
<div id="show_post">
<%= render #simple_post %>
<%= yield %>
</div>
<% end %>
</div>
_posts_actions.html.erb:
<%= simple_posts_edit_button(current_user, simple_post)%>
<%= simple_posts_delete_button(current_user, simple_post)%>
Note that you are not using the instance variable #simple_post anymore but the local one.
Now you can write your js like this:
destroy.js.erb:
<% if #simple_post %> //<-- check if "#simple_post = current_user.posts.first" still exists after destroy
$('#post-navigation').html("<%= j render partial: 'simple_posts/shared/posts_navigation', locals: { simple_post: #simple_post } %>");
$('#post-actions').html("<%= j render partial: 'simple_posts/shared/posts_actions', locals: { simple_post: #simple_post } %>");
$('#show_post').html("<%= j render #simple_post %>");
<% else %>
$('#panel').html("<%= j render partial: 'simple_posts/shared/posts_empty' %>");
<% end %>

Resources