Easy SPA Pagination¶
Pagination without reload is easy to add.
Starting point¶
Lets pretend that we're already able to see a list of posts.
Add gems¶
Lets also add Kaminari.
Add pagination¶
The changes here are almost same with the .erb
counterpart. We're using
path_to_next_page
and path_to_prev_page
which come with Kaminari.
Info
Some helpers like paginate
output HTML instead of
JSON, but we can still use more primitives methods.
# app/views/posts/index.json.props
json.rightNav do
...
end
json.posts do
json.list do
json.array! @posts do |post|
json.id post.id
json.body post.body
json.editPostPath edit_post_path(post)
end
end
+
+ json.pathToNextPage path_to_next_page(@posts)
+ json.pathToPrevPage path_to_prev_page(@posts)
end
# app/views/posts/index.js
import React from 'react'
import PostList from './PostList'
import RightNav from './RightNav'
export default PostIndex = ({
posts,
rightNav
+ pathToNextPage,
+ pathToPrevPage
}) => {
return (
<>
<PostList items={posts}>
+ <a
+ href={pathToNextPage}
+ >
+ Next Page
+ </a>
+ <a
+ href={pathToPrevPage}
+ >
+ Prev Page
+ </a>
</>
)
}
Smooth navigation¶
The above adds pagination, but each click on Next Page is a new page load.
Lets navigate without a reload. In this example, we're using data-sg-remote
,
which would set the current page's state to the response without changing the URL.
index.js
# app/views/posts/index.js
import React from 'react'
import PostList from './PostList'
import RightNav from './RightNav'
export default PostIndex = ({
posts,
rightNav,
pathToNextPage,
pathToPrevPage
}) => {
return (
<>
<PostList items={posts}>
<a
href={pathToNextPage}
+ data-sg-remote
>
Next Page
</a>
<a
href={pathToPrevPage}
+ data-sg-remote
>
Prev Page
</a>
</>
)
}
Optimize!¶
Lets skip data.rightNav
when navigating and dig for data.posts
. For the
user, only the posts lists change, but the rightNav stays the same.
Info
In effect, this achieves the same functionality as Turbo Frames, but
Superglue leans more on Unobtrusive Javascript and a simple props_at
for
better ergonomics.
index.json.props
Recall how digging for content works. We'll add a props_at
that digs for
the json.posts
while skipping other content on that page.
# app/views/posts/index.json.props
json.rightNav do
...
end
json.posts do
json.list do
json.array! @posts do |post|
json.id post.id
json.body post.body
json.editPostPath edit_post_path(post)
end
end
- json.pathToNextPage path_to_next_page(@posts)
+ json.pathToNextPage path_to_next_page(@posts, props_at: 'data.posts')
- json.pathToPrevPage path_to_prev_page(@posts)
+ json.pathToPrevPage path_to_prev_page(@posts, props_at: 'data.posts')
end