Pagination and Infinite Scroll in Phoenix
With Phoenix Hooks and Ecto Queries.
Data gets big, really big. You can optimize your data retrieval with faster algorithms, but at some point, there’s simply too much data for your client or server to handle.
That’s where Pagination comes in.
What is Pagination?
Think of your data like a big massive book. It has lines and lines of information. However, like in a regular book. We can’t store all of that information on a single page.
So like in a book we separate the information into “pages” and decide how much information should fit on a single page.
We break up hundreds of entries and can retrieve them on command by deciding how many entries should be displayed per page, and what page we want to retrieve.
Imagine you have 100 entries, and you want to retrieve page 1 with 10 entries per page. You would retrieve entries 1–10. Then when you want to retrieve page 2 with 10 entries, you would retrieve entries 11–20.
What is Infinite Scroll?
Pagination is separate from infinite scroll. You could implement pagination simply by having a load-more button that triggers your request to grab the next 10 pages.
Infinite scroll is a mechanism of triggering pagination that relies on the user scrolling down the page, and automatically triggering the load-more pagination functionality when the user gets close to the bottom of the current page of entries.
Pagination and Infinite scroll can be performed by either loading more entries and attaching them to the current set of entries, or by dynamically loading the current and next page of entries.
Loading more entries is a simpler implementation, and that’s what I’ll focus on in this article, however, it’s important to be aware that both versions exist.
To load more, retrieve the next page of data and add it to the current data set.
Load more is easier to implement and may provide a smoother less buggy scrolling experience. However, can you imagine the problem that occurs eventually? Eventually, as you scroll down, you retrieve too much data and the client gets slow and clunky again.
For many use cases, this is fine. The cause of slowness is not the amount of data, it’s the time it takes to fetch that data.
However, if you want to avoid the issue you can remove previous pages as you scroll father down.
Then re-retrieve them and remove the bottom pages if the user scrolls up.
As mentioned, I’m going to focus on the load-more implementation in this article, but once you know how to load more, then you should have all the tools you need to remove unnecessary pages from the list of data.
How Do We Code This In Phoenix?
Now that you understand the concept of pagination and infinite scrolling, how do you add it to a phoenix application?
Let’s break that into smaller and easier problems to solve.
How Do You Paginate an Ecto Query?
I’m assuming you are already knowledgeable on Ecto Queries, so if you would like a quick refresher you can read my article Ecto with Phoenix in 4 Minutes.
Using Ecto.Query methods
offset the code for pagination is pretty straightforward.
Add this paginate code to any of your existing Ecto queries and it imposes a limit (the number of entries to display per page) and an offset (the entry to start on given the current page number.
In context, this could be used to return a page of 20 entries. I’ve chosen a list of Books for the sake of example.
How Do You Handle a load-more Event In Phoenix Liveview?
Likely, you’ll have a phoenix live view function to load more data.
the current page is stored in socket assigns, and then gets incremented every time the load-more event is triggered.
The load more event retrieves the next page of books and using the ++ operator to add two lists together in phoenix, adds the next page of books to the current list of books.
How Do You Trigger The Load More Event?
You can trigger the load more event however you want, for example, you could have a “more” button that triggers the event when you scroll down far enough. In fact, that’s a great test to make sure that the event works correctly.
However, if you want to implement infinite scrolling, then one way to achieve the effect is with a phoenix hook.
The following implements an infinite_scroll hook in a file infinite_scroll.js. This attaches an event listener for “scroll” and triggers the “load-more” event anytime the scroll percent down is greater than 90.
Hooks can be imported and configured in a phoenix project using the LiveSocket configuration in app.js.
For more information on hooks see the LiveView documentation.
You can then attach this hook to an element in your template which contains your list of books.
You’ll need to make sure this element allows overflow: scroll, and possibly a height or maximum height.
You now have a much better understanding of pagination!
You have learned about
- Infinite Scrolling
- Loading more entries vs loading next entries and removing previous entries.
- Implementing pagination with Ecto queries
- Creating a load-more event to load more entries and attach them to the current data set.
- Triggering the load more event when the user scrolls down using phoenix hooks.
It’s important to say that this is just one way to implement pagination, and how you implement it in your application may differ. But by breaking down the problem into smaller ones it will be easier to understand exactly what you need to solve to get this working.
If you have any questions you can comment below or message me on Twitter at BrooklinJMyers. I will get back to you as soon as I can!