Reputation:
I have a loop of articles
, which each have one comment
presented.
The goal is to present that one comment
dynamically/asynchronously using JS.
My question is:
How do I call/activate the logic I've defined below?
#welcome/index.haml
- @articles.each do |article|
= article.title
- article.comments.each do |comment|
%comment-content{ :id => "comment-#{comment.id}" }
#welcome/comment.js.erb
// var
var comment = "#comment-<%= params[:comment_id] %>"
// render
$(comment).html("<%=j render 'comment_content' %>")
#welcome/_comment_content.haml
= comment.content
UPDATE:
While trying to solve it I thought I should add something like the following:
class WelcomeController < ApplicationController
def index
end
def comment
respond_to do |format|
format.js { render 'comment' }
end
end
Upvotes: 1
Views: 99
Reputation: 4320
Well you can use AJAX, let's say you will display the comments on ready
and on page:change
for avoid Turbolinks issue
NOTE: I will use erb since I do not feel confortable with haml.
create a route for your AJAX event, in this case we'll create a GET.
#This route will call the action get_one_comment of your articles_controller
get 'articles/get_one_comment'
In your articles_controller.rb create the get_one_comment
action, so when your ajax calls the action it retrieves the right information, from your Ajax action you will send the Article's id, so it will be available as params[:article_id]
, also make sure the action is compatible with your controller callbacks, some times a before_action
in your controller may cause issues:
#articles_controller
def get_one_comment
@article = Article.find params[:article_id]
@comment = @article.comments.last
resond_to do |format|
format.js
end
end
did you notice the respond_to
block? well as you can see this controller action will respond in a js.erb format or js.haml in your case.
The idea within our Ajax request is to loop through our articles and send the article id to the controller action, also we need to set some sort of css class or id where our response script will place the comment.
#welcome/index.html.erb
<% @articles.each do |article| %>
<div id="article-<%= article.id %>" class="article-block" data-article-id="<%= article.id %>"
<%= article.title %>
<div class="comment-section">
</div>
</div>
Now we need to create an Ajax request for load the comments asynchronously, I will use CoffeeScript, choose a file within your assets/javascripts
folder, let's say we'll choose articles.js.coffee
, so when the page loads we'll loop through all our articles and send an Ajax Request:
#articles.js.coffee
loadOneComment = ->
$('.article-block').each ->
$article_block = $(@)
$.ajax '/articles/get_one_comment',
type: 'GET'
dataType: 'script'
data: {
article_id: $article_block.data('article-id')
}
error: (jqXHR, textStatus, errorThrown) ->
console.log("AJAX Error: #{textStatus}")
success: (data, textStatus, jqXHR) ->
console.log("Worked OK!")
$(document).ready loadOneComment
$(document).on 'page:change', loadOneComment
Create a response script, in this case as we set in our controller action that we are going to answer in format.js
then we need to create a get_one_comment.js.erb
file, that will contain our response script. In this script we'll just place the comment in the page appropriately.
#get_one_comment.js.erb
$('#article-<%= @article.id %> .comment-section').append('j render(@comment)');
The above will render a partial comments/_comment.html.erb
for each article div in your page.
In case it does not work, please check your JavaScript console, I haven't tested so I may have typing mistakes, or the rails console, but basically I gave you the steps and the right method for achieve it, you can customize your AJAX, for example send the requests in a different event, like scroll, hover, click, etc...
Upvotes: 1