简体   繁体   中英

How can I update an instance variable with each ajax request?

I have a long block of comments on a view of model Page . Instead of showing all the comments on page load, I'm trying to create a "view more" button that shows the next ten comments. The button sends an ajax request to the controller, which then renders this block using jquery:

_view_more.html.erb

<% comments.each_with_index do |comment, index|%>
  <% if (( index > @start_number) && (index < @end_number) ) %>
  <%= comment.text %>
<% end %>

Let's say I always want to show the next 10 comments. I would just set @start_number = @start_number + 10 and @end_number = @end_number + 10 in the controller, but instance variables get reset, so @start_number would be nil. How can I set a variable that increases by 10 upon every ajax request?

"view more" button

<%= link_to "view more", view_more_page_path, remote: true %>

pages_controller.rb

def view_more
  @page = Page.find(params[:id])
  respond_to do |format|
    format.html { redirect_to root_path }
    format.js
  end
end

view_more

$("#comments-body").append("<%= escape_javascript(render 'view_more') %>");

I will use haml and coffee-script

When rendering comments you put an html5 data attribute with the id of the comment :

#view where to render comments
%div#comments-wrapper{:"data-pageid" => @page.id}
  =render @comments
=link_to "View more", "#", id: "view-more-link"

The comment partial

#comments/_comment.html.haml
%p.single-comment{:"data-commentid" => comment.id}
  =comment.body

application.coffee

$ ->
  $("#view-more-link").on 'click', ->
    last_comment_id = $("#comments-wrapper .single-comment").last().data('commentid')
    page_id = $("#comments-wrapper").data("pageid")
    $.ajax
      url: "/comments/view_more"
      dataType: "script"
      data:
        last_comment_id: last_comment_id
        page_id: page_id

comments_controller

def view_more
  @page = Page.find(params[:pageid])
  if params[:last_comment_id]
    @comments = @page.comments.where("comments.id > ?", params[:last_comment_id]).limit(10)
  end
  respond_to do |format|
    format.js
  end
end

comments/view_more.js.erb

$("#comments-wrapper").append("<%= escape_javascript(render @comments) %>");

Note: I don't how your routes were set up so I put the page.id as a data-attribute as well

I would use already implemented pagination gems kaminari or will_paginate . I'll create this example using will_paginate.

First of all, it's important to say that your approach is incorrect, because it loads all comments every view_more request. If you want to show 10 comments, makes sense select only they from database, right? The pagination gem will do it for you!

Let's to the code:

"view more" button

<%= link_to "view more", view_more_page_path, remote: true, id: 'view-more-btn' %>

pages_controller.rb

def view_more
  @comments = Page.find(params[:id]).comments.paginate(page: params[:page], per_page: 10)
  respond_to do |format|
    format.html { redirect_to root_path }
    format.js
  end
end

_view_more.html.erb

<% @comments.each do |comment| %>
  <%= comment.text %>
<% end %>

view_more.js.erb

$("#comments-wrapper").append("<%= escape_javascript(render 'view_more') %>");
# We need to update the 'view more' link with the next page number
$('#view-more-btn').attr('href', '<%= view_more_page_path((params[:page] || 0) + 1) %>')

is it not good to update an hidden variable before making ajax call with the count..?

var currentVal = parseInt($("[type=hidden]").val());
$("[type=hidden]").val( currentVal + 1 );

add the hidden field right at the begining of the comments section with default value as "0"

<input type="hidden" name="hiddenId" id="hiddenId" value="0">

Hope it will help

If you want a quick and dirty approach, you could save start_number and end_number inside a cookie .

But keeping track of what needs to be rendered next on client side would be a right thing to do.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM