Paginação
O Lucid tem suporte interno para paginação baseada em deslocamento. Você pode paginar os resultados de uma consulta encadeando o método .paginate
.
O método paginate
aceita o número da página como o primeiro argumento e as linhas a serem buscadas como o segundo argumento. Internamente, executamos uma consulta adicional para contar o número total de linhas.
const page = request.input('page', 1)
const limit = 10
const posts = await Database.from('posts').paginate(page, limit)
console.log(posts)
O método paginate
retorna uma instância do SimplePaginatorClass. Ele contém os metadados para a paginação, juntamente com as rows
buscadas.
SimplePaginator {
perPage: 10,
currentPage: 1,
firstPage: 1,
isEmpty: false,
total: 50,
hasTotal: true,
lastPage: 5,
hasMorePages: true,
hasPages: true
}
NOTA
É recomendável usar o método orderBy
ao usar a paginação para evitar uma ordem diferente toda vez que você consultar os dados.
Exibindo links de paginação
A seguir está um exemplo completo de exibição de links de paginação dentro de um modelo Edge.
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import Database from '@ioc:Adonis/Lucid/Database'
class PostsController {
public async index ({ request, view }: HttpContextContract) {
const page = request.input('page', 1)
const limit = 10
const posts = await Database.from('posts').paginate(page, limit)
// Altera a baseURL para os links de paginação
posts.baseUrl('/posts')
return view.render('posts/index', { posts })
}
}
Abra o arquivo posts/index.edge
e cole o seguinte trecho de código dentro dele.
<div>
@each(post in posts)
<h1>{{ post.title }}</h1>
<p> {{ excerpt(post.body, 200) }} </p>
@endeach
</div>
<hr>
<div>
@each(anchor in posts.getUrlsForRange(1, posts.lastPage))
<a href="{{ anchor.url }}">
{{ anchor.page }}
</a>
@endeach
</div>
O método getUrlsForRange
aceita um intervalo de páginas e retorna uma matriz de objetos com as seguintes propriedades.
[
{
url: '/?page=1',
page: 1,
isActive: true,
isSeperator: false,
},
{
url: '/?page=2',
page: 2,
isActive: true,
isSeperator: false,
},
// ...
]
Serializando para JSON
Você também pode serializar os resultados do paginador para JSON chamando o método toJSON
. Ele retorna os nomes das chaves em snake_case
por padrão. No entanto, você pode passar uma estratégia de nomenclatura para substituir a convenção padrão.
const posts = await Database.from('posts').paginate(page, limit)
return posts.toJSON()
{
"meta": {
"total": 50,
"per_page": 5,
"current_page": 1,
"last_page": 10,
"first_page": 1,
"first_page_url": "/?page=1",
"last_page_url": "/?page=10",
"next_page_url": "/?page=2",
"previous_page_url": null
},
"data": []
}
No exemplo a seguir, substituímos a estratégia de nomenclatura para retornar chaves em camelCase
.
const posts = await Database.from('posts').paginate(page, limit)
posts.namingStrategy = {
paginationMetaKeys() {
return {
total: 'total',
perPage: 'perPage',
currentPage: 'currentPage',
lastPage: 'lastPage',
firstPage: 'firstPage',
firstPageUrl: 'firstPageUrl',
lastPageUrl: 'lastPageUrl',
nextPageUrl: 'nextPageUrl',
previousPageUrl: 'previousPageUrl',
}
}
}
return posts.toJSON()
Você também pode atribuir uma estratégia de nomenclatura personalizada ao construtor de classe SimplePaginator
para substituí-la globalmente. O código a seguir deve ir dentro de um provedor ou um arquivo de pré-carregamento.
import { ApplicationContract } from '@ioc:Adonis/Core/Application'
export default class AppProvider {
constructor(protected app: ApplicationContract) {}
public async ready() {
const Db = this.app.container.use('Adonis/Lucid/Database')
Db.SimplePaginator.namingStrategy = {
paginationMetaKeys() {
return {
// ... o mesmo que acima
}
}
}
}
}