J'utilise will_paginate
gem dans mon projet ROR
pour afficher les enregistrements dans des pages.
Je veux que la page suivante soit chargée sans recharger toute la page en utilisant ajax
.
J'ai trouvé des exemples sur le net mais ils ne fonctionnent pas pour moi.
Comment faire ça?
Créez un nouvel assistant (par exemple, app/helpers/will_paginate_helper.rb) avec le contenu suivant:
module WillPaginateHelper
class WillPaginateJSLinkRenderer < WillPaginate::ActionView::LinkRenderer
def prepare(collection, options, template)
options[:params] ||= {}
options[:params]['_'] = nil
super(collection, options, template)
end
protected
def link(text, target, attributes = {})
if target.is_a? Fixnum
attributes[:rel] = rel_value(target)
target = url(target)
end
@template.link_to(target, attributes.merge(remote: true)) do
text.to_s.html_safe
end
end
end
def js_will_paginate(collection, options = {})
will_paginate(collection, options.merge(:renderer => WillPaginateHelper::WillPaginateJSLinkRenderer))
end
end
Dans votre vue, utilisez ensuite cette balise pour la pagination ajax:
<%= js_will_paginate @recipes %>
N'oubliez pas que les liens de pagination incluront les paramètres existants de l'URL, vous pouvez les exclure comme indiqué ci-dessous. Ceci est la fonctionnalité standard paginer:
<%= js_will_paginate @recipes, :params => { :my_excluded_param => nil } %>
J'espère que cela résoudra votre problème.
Mise à jour 1 : Ajout d'une explication de la manière dont cela fonctionne à la question d'origine où j'ai posté cette solution.
Update 2 : Je l'ai rendu compatible avec Rails 4 avec remote: true et renommé la méthode d'assistance en js_will_paginate .
Hé, si vous voulez paginer les produits, essayez ceci:
app/controllers/products_controller.rb
def index
@products = Product.paginate(page: params[:page], per_page: 10)
end
views/products/index.html.erb
<div class = "sort_paginate_ajax"><%= render 'products' %></div>
views/products/_products.html.erb
<% @products.each do |product| %>
# your code
<% end %>
<%= will_paginate @products %>
views/products/index.js.erb
$('.sort_paginate_ajax').html("<%= escape_javascript(render("products"))%>")
assets/javascripts/application.js
$(function() {
$(".sort_paginate_ajax th a, .sort_paginate_ajax .pagination a").on("click", function(){
$.getScript(this.href);
return false;
});
});
Nous appelons donc d'abord la méthode paginate sur Product pour tous les produits. Ici, un décalage sera défini en fonction de params[:page]
et la limite en fonction de per_page
options. Nous rendons également products
partial qui sera rendu à chaque fois que d'autres la page est ouverte.
Dans l'appel partiel sur @products
souhaité, puis la méthode will_paginate
est appliquée sur @products
, elle crée également params[:page]
qui est utilisé dans le contrôleur.
Maintenant, en réponse à la demande ajax, le contenu de div
est affiché avec la classe sort_paginate_ajax
avec le partiel que nous avons créé.
Également faire une requête ajax, sur le script de capture de chargement de document de toutes les balises a
dans div.sort_paginate_ajax
, et renvoyer false.
Maintenant les pages seront appelées avec une requête ajax
J'espère que cela vous aiderait.
Complément à la réponse précédente.
chaîne de code:
$(".sort_paginate_ajax th a, .sort_paginate_ajax .pagination a").on("click", function(){
remplacer par de la ficelle:
$(".sort_paginate_ajax").on("click", ".pagination a", function(){
L'événement onclick ne s'appliquait qu'aux éléments déjà existants. Ainsi, pour les nouveaux liens apparaissant, il faut un événement de délégation de clic du parent ".sort_paginate_ajax" à l'enfant ".pagination a".
Vous pouvez simplement utiliser JQuery:
Manette:
def index
@posts = Post.paginate(:page => params[:page])
respond_to do |format|
format.html
format.js
end
end
Puis dans index.html.erb:
<div id="post-content", posts: @posts >
<%= j render 'post_content' %>
</div>
Dans '_post_content.html.erb' partiel:
<%= will_paginate @posts %>
<% @posts.each do |post| %>
<p><%= post.content %></p>
<% end %>
pagination.js:
$(document).ready(function() {
$('.pagination > a').attr('data-remote', 'true');
});
index.js.erb:
$('#post-content').html("<%= j render 'post_content' %>")
Assurez-vous d'ajouter le
$('.pagination > a').attr('data-remote', 'true');
à nouveau dans votre modèle JS (index.js.erb), de sorte qu'il rétablisse les liens data-remote lors de l'exécution d'Ajax.
Pour faire suite à l’excellente réponse de @ Pierre concernant la création d’une aide, j’ai vu quelques questions complémentaires concernant la mise à jour des vues (un problème que j’avais eu au début). @Pierre poursuit avec ce problème en déclarant que vous devez créer une réponse js. Voici ce que j'ai fait après avoir créé l'aide:
dans mon show.html.erb
<div id="see-comments">
<%= render @comments %>
</div>
<div id="pagination-comments">
<%= js_will_paginate @comments %>
</div>
J'ai créé un autre fichier appelé show.js.erb (donc deux formats pour show)
// to update comments
$("#see-comments").html("<%= j render @comments %>");
// to update the pagination links
$("#pagination-comments").html('<%= js_will_paginate @comments %>');