Rails 3/Kaminari/JQuery - load more button: problem to display results (it loads the entire page layout and not only the partial layout)
Asked Answered
H

2

4

Begin with ajax and jquery combined with rails, I am trying to create a "load more" link in the bottom of my user index page. My user index page should display the 10 first users, then clicking the link it loads the next 10 users on the bottom of the user div, etc.. I use Kaminari for pagination.

I started with the following code:

User_controller.rb

def index
  @users = User.page(params[:page]).per(10)
end

User/index.html.erb

<div id="users">
  <%= render :partial => @users %>
</div>
<%= link_to "Load more", "#", :class => "next" %>

_user.html.erb

<div id="box">
  <%= link_to full_name(user), user %>
</div>

application.js

I found this snippet (credit: here) trying to fit it with my need:

function loadMore(pageNo) {
  var url = '/users?page=';
  $.get(url + pageNo, function(response) {
    $("#users").append(response);
  });
}

$(document).ready(function() {
  var currPage = 1;
  $("a.next").click(function() {
    loadMore(++currPage);
  });
});

I works perfectly except it loads all the page layout with the next results not only the box div in my _user partial How can I manage this? Did I have to create an index.js.erb (something like: page.insert_html :bottom, :users, :partial => @users but in jquery, if so how can I do it)?

Thanks for your help

Harriot answered 4/4, 2011 at 20:7 Comment(4)
I assume you mean it's rendering the layout of the page again? Is this correct? If so, please update your question with this information.Larousse
Hi Ryan, done with the update :) Yes with this it renders all the layout, no just the users div partHarriot
Hello benoitr, could you help, me, please, how you solved this problem with loading all page instead only the DIV with new items? I am solving now the same problem, but don't know, how to do... thank youSpectroscope
Hi user705586, I discontinued the project but I remember I've almost achieve this functionality. If I find the code (it's really possible I delete it) I'll post a gist here.Harriot
E
3

You should create an own action for this, associated with it's own view. Then, be sure to disable rendering of the layout:

def more_users
  @users = User.page(params[:page]).per(10)
  render :layout => false
end
Earache answered 5/4, 2011 at 5:37 Comment(4)
Hi benoitr. Yep, this would be a more_users action in the user's controller. An easy match route would do it, I think: match 'users/page/:page' => "users#more_users". The view for this action should only contain what you want to append to your div.Earache
sorry I delete my comment :) I am gonna try this. However I need a layout for what it append in my div. would it work? Thank you!Harriot
I did it! But now I am facing with 2 problems: 1.) I need to display a minimum layout (not the entire layout page but something like: <div id=box><%= link_to full_name(user), user %></div> 2.) How can I display this in my users/index.html.erb as the more_users.html.Erb view is not a partial?Harriot
Not sure if it's the best way, but I think using a _users_page.html.erb partial used both in your index.html.erb and more_users.html.erb would do it. I'm not sure if I get the first problem right, but you could add this in the _users_page.html.erb partial, or in the more_users.html.erb, depending of you want it around every entry in the list, or around the reloaded part of the list.Earache
A
9

You shouldn't need to create another action for it. I would use unobtrusive javascript. Try something like this:


User_controller.rb

you shouldn't need to change anything here, just make sure the controller responds to js

respond_to :html, :js

User/index.html.erb

<div id="users">
  <%= render :partial => @users %>
</div>
<%= link_to_next_page @users, 'Load More', :remote => true, :id=>"load_more_link" %>
<%###  link_to_next_page is a Kaminari function that returns exactly what the name implies %>

User/index.js.erb

$('#users').append("<%= escape_javascript(render :partial => @users)%>");
$('#load_more_link').replaceWith("<%= escape_javascript(link_to_next_page(@users, 'Load More', :remote => true, :id=>'load_more_link'))%>");

That should be all that is needed to get it working. Of course you can add some javascript to insert a loading icon when the link is clicked or whatever. Note: I haven't tested this exact implementation, so there may be some errors, but you should be able to get the idea

Arteriole answered 4/4, 2011 at 20:7 Comment(0)
E
3

You should create an own action for this, associated with it's own view. Then, be sure to disable rendering of the layout:

def more_users
  @users = User.page(params[:page]).per(10)
  render :layout => false
end
Earache answered 5/4, 2011 at 5:37 Comment(4)
Hi benoitr. Yep, this would be a more_users action in the user's controller. An easy match route would do it, I think: match 'users/page/:page' => "users#more_users". The view for this action should only contain what you want to append to your div.Earache
sorry I delete my comment :) I am gonna try this. However I need a layout for what it append in my div. would it work? Thank you!Harriot
I did it! But now I am facing with 2 problems: 1.) I need to display a minimum layout (not the entire layout page but something like: <div id=box><%= link_to full_name(user), user %></div> 2.) How can I display this in my users/index.html.erb as the more_users.html.Erb view is not a partial?Harriot
Not sure if it's the best way, but I think using a _users_page.html.erb partial used both in your index.html.erb and more_users.html.erb would do it. I'm not sure if I get the first problem right, but you could add this in the _users_page.html.erb partial, or in the more_users.html.erb, depending of you want it around every entry in the list, or around the reloaded part of the list.Earache

© 2022 - 2024 — McMap. All rights reserved.