- you need to make sure the controller knows which page link of which listing you press. we do this by passing a param to will_paginate page link generator.
- you need to make sure your js updates the correct html tag when refreshing the pagination of either listing. we do this by wrapping the pagination in a mood-dependent :) div tag.
- since we share the partial we need to make sure mood as well as correct collection is set in controller and passed to partial as local from index views (both html and js).
- finally make sure your ajax remote picks up after you redraw pagination (this is a bonus)
so, to set controller instance vars depending on request mood parameter
- note that this code also spares you some db calls, since if you just pagintae sad users you do not need to retrieve happy ones or all).
- I ommit @users for simplicity, its never used
- I suspect happy scope for sad users is only a typo
.
# controller
def index
@mood = params[:mood]
@mood_users = @happy_users = User.happy_scope.paginate(:page => params[:page], :per_page => 5) if @mood.blank? || @mood == 'happy'
@mood_users = @sad_users = User.happy_scope.paginate(:page => params[:page], :per_page => 5) if @mood.blank? || @mood == 'sad'
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @users }
format.json { render :json => @users }
format.js
end
end
make sure we dispatch the right locals to partials:
# index.html.erb
<%= render :partial => 'users/user', :locals => {:users => @happy_users, :mood => 'happy' } %>
<%= render :partial => 'users/user', :locals => {:users => @sad_users, :mood => 'sad' } %>
make partial mood sensitive allowing for distinct div tag id. also put mood in request url.
# users/user partial
<div id='<%= "#{mood || ''}users"%>'>
<% users.each do |user| %>
Show some fields
<% end %>
<%= will_paginate users, :params => { :mood => mood } %>
</div>
this js allows for refreshing different collections in different divs depending on which pagination link was pressed.
# index.js.erb
$("#<%= @mood %>users").html('
<%= escape_javascript(render(partial: "users/user", locals: { users: @mood_users, mood: @mood })) %>
');
For unobtrusive ajax links for pagination you need.
Ruby - Rails 3 - AJAXinate Paginate and sorting
# in a generic js
$(document).ready(function () {
$(".pagination").find("a").livequery(function () {
$(this).attr("data-remote", true);
});
});
Note that the solution should even work if javascript is not enabled and we fall back on html. In this case both sections should be redisplayed allowing for different pages.
MODIFIED CODE TO ALSO HANDLE GRACEFUL JS FALLBACK TO HTML
controller
# controller
def index
@mood = params[:mood]
@happy_page = @mood == 'happy' ? params[:page] : params[:happy_page]
@sad_page = @mood == 'sad' ? params[:page] : params[:sad_page]
@mood_users = @happy_users = User.happy_scope.paginate(:page => @happy_page, :per_page => 5) if !request.xhr? || @mood == 'happy'
@mood_users = @sad_users = User.happy_scope.paginate(:page => @sad_page, :per_page => 5) if !request.xhr? || @mood == 'sad'
@mood_users = @users = User.scoped.paginate(:page => params[:page], :per_page => 5) if @mood.blank?
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @users }
format.json { render :json => @users }
format.js
end
end
forward new view vars to partial local
# index.html.erb
<%= render :partial => 'users/user', :locals => {:users => @happy_users, :mood => 'happy', :happy_page => @happy_page, :sad_page => @sad_page } %>
<%= render :partial => 'users/user', :locals => {:users => @sad_users, :mood => 'sad', :happy_page => @happy_page, :sad_page => @sad_page } %>
we only need to pass this here to not get undefined method in partial.
# index.js.erb (fixed HTML syntax)
$("#<%= @mood %>users").html('
<%= escape_javascript(render(partial: "users/user", locals: { users: @mood_users, mood: @mood, :happy_page => @happy_page, :sad_page => @sad_page })) %>
');
this will then persist happy pages in param if sad page link is clicked, and vica versa.
# users/user partial
<div id='<%= "#{mood || ''}users"%>'>
<% users.each do |user| %>
Show some fields
<% end %>
<%= will_paginate users, :params => { :mood => mood, :happy_page => happy_page, :sad_page => sad_page %>
</div>
@user
but falls apart when I try to pass as a local. Is there any reason why will_paginate would not accept a local? – Estellescape_javascript(render("users/user"))
would require me having two index.html.erb files, correct? One for each collection that I need to render? – Estell