user4932805
user4932805

Reputation:

How to use AJAX in rails Views

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

Answers (1)

svelandiag
svelandiag

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.

Step 1: define a route

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'

Step 2: Define your controller action

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.

Step 3: Fix your markup

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>

Step 4: Add the Ajax

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

Step 5: render the comment, using the response script.

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

Related Questions