snowflakekiller
snowflakekiller

Reputation: 3568

remove comment from view using AJAX rails

I have a directory app that has comments. I add and delete comments with remote: true and I want to fade them out in my view with Jquery.

How do I go about getting a reference to the comment I want to fade out in the view? I can delete the comment just fine, but I don't know how to fade the comment out in my view

Here is my controller:

class CommentsController < ApplicationController
  def create
    business = Business.find(params[:business_id])
    new_comment = business.comments.create
    new_comment.comment = params[:comment_text]
    new_comment.save
    respond_to do |format|
      format.html {redirect_to business}
      format.js
    end
  end

  def destroy
    business = Business.find(params[:business])
    comment = Comment.find(params[:id])
    comment.destroy!
    params[:id] = business.id
    respond_to do |format|
      format.html {redirect_to business_url(id: params[:id])}
      format.js 
    end
  end
end

Comments are rendered in my business view like this:

<aside class="comment-section">
    <h4 class="thin-grey-underline"><span class="glyphicon glyphicon-comment glyphicon-left-space"></span> Reviews </h4>
    <% if [email protected]? %>
      <% @business.comments.each do |comment| %>
        <div id="comments">
          <%= render partial: 'comment', locals: {comment: comment, business: @business} %>
        </div>
      <% end %>
    <% else %>
      <p> No reviews yet... </p>
    <% end %>
    <%= render partial: 'comments_form' %>
  </aside>

my single comment partial:

<div class="row single-comment vertical-align">
  <div class="col-sm-12 col-md-3">
    <div class="profile-image" style="background: url('<%= business.profile_image_url(:thumb).to_s %>') no-repeat; background-position:center"></div>
  </div>
  <div class="col-sm-12 col-md-9">
    <h5><%= comment.title %></h5>
    <p><%= comment.comment %></p>
    <%= button_to(business_comment_path(@business.id,comment.id), {method: :delete, remote: true, class:"btn btn-danger delete-comment-button pull-right", params:{id: comment.id, business: business.id}} ) do%>
      <i class="glyphicon glyphicon-trash"></i>
    <% end %>
  </div>
</div>

the form partial to create a new comment:

<div class="row">
  <div class="col-sm-12 col-md-12">
    <div class="comments-form">
      <%= form_tag(business_comments_path(@business), html: { id: "comment-form" }, method: 'post', remote: true) do %>
        <h5 class="thin-grey-underline"><span class="glyphicon glyphicon-pencil glyphicon-left-space"></span> Write a Review </h5>
        <%= text_area_tag(:comment_text,nil, class: "comment-form-input")%>
        <%= hidden_field_tag 'business_id', params[:id] %>
        <%= submit_tag("Comment", class:"btn btn-primary") %>
      <% end %>
    </div>
  </div>
</div>

If I have a list of comments, how do I delete a specific comment by clicking on the delete link and also have it removed from my view in a fadeout manner?

I have a destroy.js.erb file that gets called, but I don't know how to get a reference to fade out the specific comment.. not sure if I am explaining myself clearly here

Upvotes: 0

Views: 807

Answers (4)

faron
faron

Reputation: 1059

You can use helper dom_id method (docs):

  • Change <div id="comments"> to <div id="<%= dom_id comment %>"> or add id attribute to div.single-comment
  • In js response do $('#<%= dom_id @comment %>').fadeOut();

Another option is to bind to jQuery event like this:

$('body').on('ajax:success', '.delete-comment-button', function(event) {
  $(event.original_target).closest('.single-comment').fadeOut();
})

Then you can just return status 2XX for the delete request

Upvotes: 0

Max Williams
Max Williams

Reputation: 32943

First step is to make sure that the thing you want to delete has a unique id, and that this id is easy to generate. I patched AR::Base with an instance method called dom_id for this, which is like so:

def dom_id
  "#{self.class.name.underscore}-#{self.id}"
end

which means if i'm rendering out a list of Foo objects i can do something like

<%= render :partial => "foos/foo", :collection => @foos %>

and in the partial do this

<li id="<%= foo.dom_id %>">
....
</li>

and the id will be something like "foo-123".

Now, in my destroy.js.erb action, after deleting a foo object, i know that it's dom id on the page can be got with @foo.dom_id. To fade it out and delete it i would then do

page << "$('##{@foo.dom_id}').fadeOut('slow', function(){$(this).remove();});"

Upvotes: 0

hww
hww

Reputation: 11

Knockoutjs can do that The "if" binding

Upvotes: 0

Drew
Drew

Reputation: 2621

You could try something like this:

In your comment partial:

<div id="comment_<%= comment.id %>" class="row single-comment vertical-align">

destroy.js.erb:

$('#comment_<%= @comment.id %>').remove();

Upvotes: 3

Related Questions