Adding pagination to a Rails JSONAPI backed Ember app is not a totally plug-and-play development task, which is what I would have expected. There is of course ember-cli-pagination which is a library that tries to make pagination as simple as possible. Unfortunately, I wasn’t able to get that working out of the box and it didn’t seem like the type of library I wanted to put the effort into banging on to make work. Luckily, I found this awesome post on EmberIgniter.com which covers pagination using the JSONAPI spec very nicely. This post and the code that follows is heavily based off of that post, so big thanks to @thefrank06 for paving the way. This post is fairly similar to that one however it is made to be a bit more for the advanced Emberino, more reuse friendly, and focuses on using the jsonapi-resources Rails gem. Keep reading if that sounds of interest!

Setup

Before we begin, let’s make sure we’re on the same page in regards to our dependencies. Here is what you should have in place:

A jsonapi-resources Rails API

Rails API An Ember-CLI frontend using Ember Data

ember-truth-helpers installed (cause it's a great lib and allows us to skip adding a handlebars helper).

installed (cause it's a great lib and allows us to skip adding a handlebars helper). A model you’re looking to paginate. Using the classic blog example, I’ll refer to this as “Post” from now on.

An understanding of how query params work in Emberjs Apps.

Got all that? Great, we’re ready to go.

jsonapi-resources Updates

A couple simple things need to get added to our backend app to enable our pagination via jsonapi-resources . Let me throw some code at you:

So what are we doing here? First, we create an jsonapi-resources initializer (or append to our existing one) so we can let jsonapi know that we'd like to include the page count in our meta object when requesting an index route for our models. Second, we're updating our PostResource (which is our JSON blueprint) to have a paginator so the API knows what we're talking about when we send it page number and page size query params later on. We're using the :paged paginator here as that is likely what you're looking to do, but if you'd like to do offset or your own custom pagination rules then check out these docs.

This is why I love jsonapi-resources : It’s that simple! Our backend is good to go, so let’s jump over to the frontend side of things.

Ember Updates

A few things need to happen to the frontend to make pagination come together:

We need to update our ApplicationSerializer so it pulls our pagination meta information and makes it available to us. We need to properly request the page number and page size when fetching our model at the Route layer. We need to add our query params to our Controller and make sure they have some defaults. Finally, we need to provide a UI to our user’s so they can page through the Posts.

Let’s attack those one-by-one!

Application Serializer Update

The above code (which is a slightly altered version of our friend @thefrank06 original code) is an Ember.Mixin that you should add to your ApplicationSerilaizer . I broke this out as a Mixin so that it gives this functionality a name so it is obvious what it is doing, but feel free to copy/paste those methods into your serializer if you don't want to add another file. If you don't already have an application serializer you can generate one via ember g serializer application .

The Mixin does some pulling apart of the links JSON returned by the API to create a meta.pagination object on our DS.RecordArray . We'll use that pagination object later to create the links needed to paginate via our routes.

Update our Route to query properly

Here we update our PostsRoute to query for our model using the params 'page' and 'size'. This creates requests like /posts?page[number]=1&page[size]=20 to our backend, which properly returns the paginated result. The queryParams declaration on the bottom half makes it so our route knows to reload when those params change.

Update our Controller to declare our query params

To make our pagination as re-useable as possible across different routes, we’ve got a PaginationControllerMixin . We add that to our PostsController and we've properly wired up Ember to insert our query params into the URL.

Add our pagination links to the UI

Lastly, we’ve got to give the user some links to page through our Posts. We’ll do that in the form of a simple component named paginator-links :

Here we’ve got our component getting passed the meta.pagination object that our PaginationSerializer created as well as the name of the route that we're paginating over. Our component takes these in and spits out links to allow the user to paginate over.

By the way, this is BYOCSS. The paginator-links doesn't look pretty by any means, but it's functional.

Wrapping Up

Using the above, we’ve got some reusable pagination goodness going on. Our jsonapi-resources backend properly speaks pagination, our Ember App has a reusable set of Mixins to support pagination, and we've got a handy Component to render the needed links for paginating. This pattern gives us a pretty straight forward way to paginate and I know I walked away from it happy.

Have an improvement or noticed something I missed? Let me know in the comments or ping me at matt@masterpoint.io!