The Problem
In my PM roadmap, I had some minor improvements for the scrolling of users in Kubukisa, one of my passion projects. Below is how I had it initially using the pagy gem.
Not really the best-looking pagination if you are a perfectionist like me. I mean, it can do but why not improve it, right?! For the purposes of this article, I will use my personal site for reference, particularly, the POST
resource on how to go about implementing infinite scrolling.
Get started
To get started, you need to install Hotwire Turbo in your app. For Rails apps, you need the gem, this will be important as we’ll be using turbo_streams
. Next, you will need to include the Pagy Countless subclass which is useful for saving one count query per request, this will be important later in the implementation.
PS: Remember to restart your server, I had errors until I restarted the server.
In your posts_controller.rb
, include Pagy.
In your Index method, set up Pagy’s Countless subclass.
You don’t need the WHERE clause if you don’t have conditions you would like to set for your resources. You will also need to explicitly indicate the formats the index view will respond to. You will later see how to set these up. The respond_to
block is a helper method on the superclass PostsController
that takes |format|
as the argument to the block. This Rails helper method references the response that will be sent to the View (i.e. on the browser).
From here, in your views, particularly, the index view, declutter your view and use partials as below:
I use Tailwind CSS for my projects, in case you use Bootstrap, etc. you can discard my classes. What is most important here is including the id
of posts (highlighted above) which is what turbo will be used to reference the posts on each query.
Back in the index view, you need to set up the rendering of the above partial view (you can read more on partials here) as well as the turbo_stream_tag
helper to create a turbo stream.
Here, you will notice that the div
wrapping the posts partial has an id
which is important. This id
is named according to your resource, e.g. articles
or towns
. The turbo_frame_tag
is lady loaded and most importantly, pulls the queries from the posts_path
and displays the queries in the turbo_stream
format we defined on the posts_controller
respond_to
helper method.
I hope you are still following and everything is starting to come together.
We further will need to create the index.turbo_stream.erb
view for turbo.
Here, we have to wrap the posts
partial in a turbo_stream and append it with the posts
resource. The turbo_frame_tag
is similar to that in the index.html.erb
and does the same thing. To prevent the loading to be infinitely looped, you will have to include page: @pagy.next
which checks the size of the paginated collection (@records
) in order to know if it is the last page or not.
There you have it, you now have infinite scrolling.
How would you better optimize this feature? @ mention me on Twitter (@ThubaMamba) or LinkedIn (@thubamamba) and let’s keep the conversation going. Keep building and shipping cool stuff.