comments not rendering with ajax in rails - javascript

I am try to render my comments with ajax in my rails app...but it is not working and the comments diplay just after I redirect the page...so the comment get created successfully but the problem is rendering comments with ajax and jquery!!!!
I have this lines in my application.html.erb:
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= csrf_meta_tags %>
and this require line in my application.js:
//= require jquery
//= require jquery_ujs
here is my show.html.erb file under posts :
<div id="posts" class="transitions-enabled">
<div class="box panel panel-default">
<%= render 'post', post: #post %>
</div>
</div>
my _post partial:
<div class="panel-body">
<%= link_to image_tag(post.user.avatar.url, size: "50x50", class: "img-circle"), profile_path(post.user.user_name) %>
<ul class="posts-shows">
<li><strong><%= link_to post.user.user_name, profile_path(post.user.user_name) %></strong></li>
<li><small><%= link_to "#{time_ago_in_words(post.created_at)} ago", post_path(post), class: "time-link" %></small></li>
</ul>
<p class="disc-posts"><%= post.description %></p>
<%= link_to image_tag(post.image.url(:large), class: "img-responsive img-in" ) %><br/>
<% if post.user == current_user %>
<div><%= link_to "Edit", edit_post_path(post) %> | <%= link_to "delete", post, method: :delete, data: {confirm: "Are you sure?"} %> </div>
<% else %>
<div><%= link_to "Repost", repost_post_path(post), method: :post, data: { confirm: "Are you sure?"} if user_signed_in? %></div>
<% end %>
</div>
<div class="panel-footer">
<div class="comment-form">
<%= form_for([post, post.comments.build], remote: true) do |f| %>
<%= f.text_field :content, placeholder: 'Add a comment...', class: "form-control comment_content", id: "comment_content_#{post.id}" %>
<% end %>
</div>
<div class="comments" id= "comments_#{post.id}">
<% if post.comments.present? %>
<%= render post.comments, post: post %>
<% end %>
</div>
</div>
my _comment.html.erb in comments folder:
<% if comment.user_id.present? %>
<div id="comment">
<%= link_to image_tag(post.user.avatar.url, size: "30x30", class: "img-circle img-comments"), profile_path(comment.user.user_name) %>
<div class="user-name">
<%= link_to comment.user.user_name, profile_path(comment.user.user_name), class: "username-size" %>
</div>
<div class="comment-content">
<%= comment.content %>
</div>
</div>
<% end %>
and here is the create.js.erb under comments folder :
$('#comments_<%= #post.id %>').append("<%=j render 'comments/comment', post: #post, comment: #comment %>");
$('#comment_content_<%= #post.id %>').val('')
and my comments controller:
class CommentsController < ApplicationController
before_action :set_post
def index
#comments = #post.comment.all
end
def new
#comment = #post.comments.build(comments_params)
end
def create
#comment = #post.comments.build(comments_params)
#comment.user_id = current_user.id
if #comment.save
respond_to do |format|
format.html { redirect_to root_path }
format.js
end
else
flash[:alert] = "Check the comment form, something went horribly wrong."
render root_path
end
end
def destroy
#comment = #post.comments.find(params[:id])
#comment.destroy
flash[:success] = "Comment deleted :("
redirect_to root_path
end
private
def comments_params
params.require(:comment).permit(:content)
end
def set_post
#post = Post.find(params[:post_id])
end
end

I don't think this line is right -
<div class="comments" id= "comments_#{post.id}">
I think you need this
<div class="comments" id= "comments_<%= post.id %>">

Related

Can't fetch comments in ajax + Rails

Want to add a comment feature with ajax in Rails. I can't fetch comments after posting automatically. It's not working.
An error:
ActionView::Template::Error (undefined method `each' for nil:NilClass):
controllers/posts_controller.rb
class PostsController < ApplicationController
def create
#post = Post.new(create_params)
if #post.save
render :index
end
end
private
def create_params
params.require(:post).permit(:content)
end
end
controllers/home_controller.rb
class HomeController < ApplicationController
def index
#post = Post.new
#posts = Post.all
end
end
views/home/index.html.erb
<div id="postForm">
<%= render partial: 'posts/form', locals: { post: #post } %>
</div>
<div class="postContainer" id="postArea">
<ul>
<%= render partial: 'posts/index', locals: { posts: #posts } %>
</ul>
</div>
views/posts/index.js.erb
$("#postArea").html("<%= j(render 'index', { posts: #posts }) %>")
$("textarea").val('')
views/posts/_index.html.erb
<ul>
<% posts.each do |post| %>
<li><%= post.content %></li>
<% end %>
</ul>
views/posts/_form.html.erb
<%= form_with(model: post, url: posts_path) do |f| %>
<form>
<div class="form-group">
<label for="contents">Content</label>
<%= f.text_area :content, class: "form-control", rows: "2" %>
</div>
<div>
<%= f.submit "Submit", type: "submit", class: "btn btn-primary" %>
</div>
<% end %>
I have fixed it done.
controllers/posts_controller.rb
def create
#post = Post.new(create_params)
if #post.save
render :index
end
end
views/posts/_index.html.erb
<ul>
<% #posts.each do |post| %>
<li><%= post.content %></li>
<% end %>
</ul>

Check for current page in a js file to render out different partials

I have implemented a favorites system into my rails app, which works on the individual show page for the Tracks model. This is all handled through the Favorites controller, so I am attempting to use the same js file for both index and show pages. This is what I have tried so far. It works if I only have the show page material, the javascript doesn't work at all for either if I do it this way.
favorite.js.erb
<% if current_page?(track_path(#track)) %>
$("#favorites").html("<%= escape_javascript(render('tracks/favorites')) %>");
<% else %>
$("#favorites").html("<%= escape_javascript(render('albums/favorites')) %>");
<% end %>
the partial for tracks/favorites
<% if user_signed_in? && current_user.favorited?(#track) %>
<%= link_to image_tag('icons/heart_full.svg', width: 20), track_unfavorite_path(#track), method: :post, remote: true %>
<% else %>
<%= link_to image_tag('icons/heart_empty.svg', width: 20), track_favorite_path(#track), method: :post, remote: true %>
<% end %>
the partial for albums/favorites
<% if user_signed_in? && current_user.favorited?(track) %>
<%= link_to image_tag('icons/heart_full.svg', width: 20), track_unfavorite_path(track),
method: :post, remote: true %> <%= pluralize( track.favorites.count, 'favorite' ) %>
<% else %>
<%= link_to image_tag('icons/heart_empty.svg', width: 20), track_favorite_path(track),
method: :post, remote: true %> <%= pluralize( track.favorites.count, 'favorite' ) %>
<% end %>
Passing the instance variable as the parameter works for the show page, but trying to do it for the loop results is what is confusing me.
favorites_controller.rb
class FavoritesController < ApplicationController
before_action :authenticate_user!
before_action :find_track
def favorite
#track.favorites.where(user_id: current_user.id).first_or_create
respond_to do |format|
format.html { redirect_to #track }
format.js
end
end
def unfavorite
#track.favorites.where(user_id: current_user.id).destroy_all
respond_to do |format|
format.html { redirect_to #track }
format.js
end
end
private
def find_track
#track = Track.find(params[:track_id])
end
end
The view for Track show page is simple:
<div id="favorites">
<%= render 'tracks/favorites' %>
</div>
The view for the loop on the index page:
<% #tracks.each do |track| %>
<div class="track_thumbnail">
<% if track.avatar? %>
<%= link_to image_tag(track.avatar.url), track_path(track), width: 100, title: track.title %>
<% else %>
<%= link_to image_tag(track.user.avatar.url), track_path(track), width: 100, title: track.title %>
<% end %>
<%= link_to track.user.username, user_path(track.user) %>
</div>
<div class="track_overview">
<h2><%= link_to track.title, track_path(track) %><% if track.explicit == "explicit" %> (explicit)<% end %></h2>
<p class="description"><%= truncate(track.description, length: 160) %></p>
<div class="icons_container">
<div id="favorites">
<%= render 'albums/favorites', :track => track %>
</div>
</div>
</div>
<% end %>

trouble using create method with AJAX

I am trying to use AJAX functionality in order to create a new Task in a simple ToDo list application.
Currently the list is set up like this:
<h2> TO DO </h2>
<div class="wrapper">
<ul id="incomplete">
<% #task.each do |f| %>
<% if f.complete == false %>
<div id="<%= f.id %>">
<p class= "title"><%= f.title %></p>
<%= form_for f, remote: true do |task| %>
<%= task.check_box :complete, class: "check_box" %>
<%= task.submit %>
<% end %>
</div>
<% end %>
<% end %>
</ul>
</div>
<h2> COMPLETED </h2>
<div class="wrapper">
<ul id="completed">
<% #task.each do |f| %>
<% if f.complete == true %>
<div id="<%= f.id %>">
<p class="title"><%= f.title %></p>
<%= form_for f, remote: true do |task| %>
<%= task.check_box :complete, class: "check_box" %>
<%= task.submit %>
<% end %>
</div>
<% end %>
<% end %>
</ul>
</div>
<p id="new_link"><%= link_to "New Task", new_task_path, remote: true %></p>
<div id="new_task">
</div>
When the "New Task" link is pressed, it executes a js file which loads the following partial:
<%= form_for #task, remote: true do |f| %>
<%= f.label :title %>
<%= f.text_field :title %>
<%= f.submit "Create" %>
<% end %>
My create method is below:
def create
#task = Task.new(task_params)
#task.save
respond_to do |format|
format.html
format.js
end
end
When I remove the "remote: true" from my partial form, page resets and the new task appears in the new , however, when I do use the "remote: true", and execute my create.js.erb file, nothing is changed in the DOM. Here is my create.js.erb file:
$('#incomplete').append($("#<%= #task.id %>"));
console.log("<%= #task.title %> has been saved.");
I'm not receiving any errors in my consoles, and the console.log line on the create.js.erb logs to the console without a problem the task title and the rest of the string.
I'm pretty lost in why the create.js.erb file is not manipulating the DOM. This code provides no response visually, only the post to the console.

How to display flash messages, on successful ajax, at the top of my page, without refreshing?

My bookmarks index page is essentially a single page application. When I submit the form for a new bookmark at the bottom of my page, I want the page to not have to refresh and display "Bookmark successfully created!" in the form of a flash message at the top of the page.
In my application.html.erb file, I am rendering flash messages:
<!DOCTYPE html>
<html>
<head>
<title>Text Me Later</title>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= csrf_meta_tags %>
</head>
<body>
<%= render partial: 'layouts/nav' %>
<% flash.each do |key, value| %>
<% if key == "notice" %>
<%= content_tag :div, value, class: "text-center alert alert-warning" %>
<% elsif key == "alert" %>
<%= content_tag :div, value, class: "text-center alert alert-danger" %>
<% else %>
<%= content_tag :div, value, class: "text-center alert alert-success" %>
<% end %>
<% end %>
<div class="container">
<%= yield %>
<%= debug(params) if Rails.env.development? %>
</body>
</html>
The create method in my bookmarks_controller:
def create
#bookmark = Bookmark.new bookmark_params
#bookmark.user_id = current_user.id
respond_to do |format|
if #bookmark.save
flash[:notice] = 'Bookmark was successfully created.'
format.html {
redirect_to user_bookmarks_path
}
format.json {
render json: #bookmark,
status: :created,
location: #bookmark
}
format.js {}
else
flash[:error] = "Bookmark could not be created."
format.html {
render :index
}
format.json {
render json: #bookmark.errors.full_messages
}
format.js {}
end
end
end
My bookmarks index.html.erbfile:
<h2>All of <%= current_user.first_name %>'s Bookmarks</h2>
<ul id="all-bookmarks">
<% #bookmarks.each do |bookmark| %>
<li class="bookmark-div">
<div><%= bookmark.title %></div>
<div><%= bookmark.image %></div>
<div><%= bookmark.description %></div>
<div><%= bookmark.location %></div>
<div><%= bookmark.time %></div>
<div><%= bookmark.date %></div>
<div><%= bookmark.created_at %></div>
<div><%= bookmark.updated_at %></div>
<div><%= bookmark.url %></div>
<div><%= link_to "Edit", [:edit, bookmark]%></div>
<div><%= link_to "Delete Bookmark", bookmark, :method => :delete, confirm: 'are you sure?'%></div>
<div><%= link_to "Add as a reminder" %></div>
</li>
<% end %>
</ul>
<h2>Add a bookmark below:</h2>
<div id="post-new-bookmark">
<%= simple_form_for [#user, #bookmark], :method => :post, remote: true do |f| %>
<% if #bookmark.errors.any? %>
<div id="errorExplanation">
<h2><%= pluralize(#bookmark.errors.count, "error") %> prohibited this post from being saved:</h2>
<% end %>
<%= f.input :title %>
<%= f.input :image %>
<%= f.input :description %>
<%= f.input :location %>
<%= f.input :date %>
<%= f.button :submit %>
<% end %>
</div>
create.js.erb:
$("<%= escape_javascript(flash[:notice]) %>").appendTo("#flash-notice")
$("<%= escape_javascript render(:partial => 'bookmarks/cbookmark', :locals => { :bookmark => #bookmark }) %>").appendTo("#all-bookmarks")
My question is: Why is the flash message on successful bookmark creation not displaying at the top of the page right after a successful creation? Shouldn't the flash message handling in my application.html.erbtake care of it? Could it be due to a syntax error in my bookmark controller?
I also have a question about flash.now vs flash. Is that relevant in this case since the bookmark submission is an AJAX action?
form of a flash message
Ce ne pas possible avec le flash de Rails
--
The flash forms part of the session cookie that Rails populates between actions. This has been notoriously difficult to parse with Ajax, and indeed remains a difficult pattern to implement (how can Rails repopulate the session when your browser hasn't been refreshed).
The way to go about it is to pass the value through your ajax method, using flash.now. Good ref here (I wrote about it):
#app/controllers/bookmarks_controller.rb
class BookmarksController < ApplicationController
def create
#bookmark = Bookmark.new bookmark_params
#bookmark.user_id = current_user.id
respond_to do |format|
if #bookmark.save
flash.now[:notice] = 'Bookmark was successfully created.'
format.html { redirect_to user_bookmarks_path }
format.json { render json: #bookmark, status: :created, location: #bookmark }
format.js
else
flash.now[:error] = "Bookmark could not be created."
format.html { render :index }
format.json { render json: #bookmark.errors.full_messages }
format.js
end
end
end
end
Using flash.now should allow you to populate the flash through Ajax accordingly:
#app/views/bookmarks/create.js.erb
$("<%=j flash.now[:notice] %>").appendTo("#flash-notice")

Rails Ajax Not Reloading

Creating real time chat app, but whenever I post a message I have to reload the page to see my new message. The chat does not reload by itself.
_form.html.erb
<div class="well">
<%= form_for #comment, remote: true do |f| %>
<div class="form-group">
<%= f.label :body, 'Enter your comment:' %>
<%= f.text_area :body, rows: 3, class: 'form-control', required: true, maxlength: 2000 %>
<small class="label label-warning">Cannot be blank or contain more than 2000 symbols.</small>
</div>
<%= f.submit 'Post', class: 'btn btn-primary btn-lg' %>
<% end %>
</div>
_comments.html.erb
<li class="media comment">
<%= link_to image_tag(comment.user.avatar_url, alt: comment.user.name, class: "media-object"),
comment.user.profile_url, target: '_blank', class: 'pull-left' %>
<div class="media-body">
<h4 class="media-heading"><%= link_to comment.user.name, comment.user.profile_url, target: '_blank' %> says
<small class="text-muted">[at <%= comment.created_at.strftime('%-d %B %Y, %H:%M:%S') %>]</small></h4>
<p><%= comment.body %></p>
</div>
</li>
create.js.erb
publisher = client.publish('/comments', {
message: '<%= j render #comment %>'
});
publisher.callback(function() {
$('#comment_body').val('');
$('#new_comment').find("input[type='submit']").val('Submit').prop('disabled', false)
});
publisher.errback(function() {
alert('There was an error while posting your comment.');
});
git source
Edit: added comments_controller.rb
class CommentsController < ApplicationController
def new
#comment = Comment.new
#comments = Comment.order('created_at DESC')
end
def create
respond_to do |format|
if current_user
#comment = current_user.comments.build(comment_params)
if #comment.save
flash.now[:success] = 'Your comment was successfully posted!'
else
flash.now[:error] = 'Your comment cannot be saved.'
end
format.html {redirect_to root_url}
format.js
else
format.html {redirect_to root_url}
format.js {render nothing: true}
end
end
end
private
def comment_params
params.require(:comment).permit(:body)
end
end

Categories