Lógica de Paginação com Angular
Este é um exemplo de como implementar uma paginação em Angular 2 com uma lógica como a do Google.
Lógica de paginação do Google
A lógica na paginação do Google é a seguinte:
Há 10 links de página mostrados a qualquer momento (por exemplo, 1 2 3 4 5 6 7 8 9 10) a menos que haja menos de 10 páginas totais o link ativo (página atual) está na 6ª posição, exceto quando o link ativo da página está abaixo de 6 ou a menos de 4 da última posição
Aqui está o que parece para cada página se houver 15 páginas totais:
Executando o Exemplo Angular 2 Localmente
Foi usado o projeto angular 2 quickstart como uma base para o aplicativo, ele é escrito em TypeScript e usa systemjs para carregar módulos. Também é possivel usar o angular-cli para o aplicativo importando os componetes e services. Se você é novo no angular 2, eu recomendaria verificar o curos de angular 2 da Loiane Groner, pois ela ensina em detalhes sobre como criar projetos com angular-cli.
-
Instale NodeJS e NPM de nodejs.org, você pode verificar as versões que você instalou executando
node -v
enpm -v
da linha de comando. -
Faça o download do código-fonte do projeto em github.com/cornflourblue/angular2-pagination-example
-
Instale todos os pacotes necessários com
npm install
npm é executando a partir da linha de comando na pasta raiz do projeto (onde o package.json está localizado). -
Inicie o aplicativo executando
npm start
a partir da linha de comando na pasta raiz do projeto.
Pager Service - Lógica de paginação em TypeScript como a do Google
Para facilitar a reutilização da lógica de paginação em diferentes componentes ou módulos Angular 2, colocamos a lógica de paginação em um serviço angular 2.
import * as _ from 'underscore';
export class PagerService {
getPager(totalItems: number, currentPage: number = 1, pageSize: number = 10) {
// calculando o total de paginas
let totalPages = Math.ceil(totalItems / pageSize);
let startPage: number, endPage: number;
if (totalPages <= 10) {
// Se tiver menos de 10 páginas totais para mostrar tudo
startPage = 1;
endPage = totalPages;
} else {
// Se tiver mais de 10 páginas totais, calcular as páginas inicial e final
if (currentPage <= 6) {
startPage = 1;
endPage = 10;
} else if (currentPage + 4 >= totalPages) {
startPage = totalPages - 9;
endPage = totalPages;
} else {
startPage = currentPage - 5;
endPage = currentPage + 4;
}
}
// Cálculo de índices de itens iniciais e finais
let startIndex = (currentPage - 1) * pageSize;
let endIndex = Math.min(startIndex + pageSize - 1, totalItems - 1);
// Criar um array de páginas para o ng-repeat no componente
let pages = _.range(startPage, endPage + 1);
// Retornar objeto com todas as propriedades exigidas para exibição
return {
totalItems: totalItems,
currentPage: currentPage,
pageSize: pageSize,
totalPages: totalPages,
startPage: startPage,
endPage: endPage,
startIndex: startIndex,
endIndex: endIndex,
pages: pages,
};
}
}
import * as _ from 'underscore';
export class PagerService {
getPager(totalItems: number, currentPage: number = 1, pageSize: number = 10) {
// calculando o total de paginas
let totalPages = Math.ceil(totalItems / pageSize);
let startPage: number, endPage: number;
if (totalPages <= 10) {
// Se tiver menos de 10 páginas totais para mostrar tudo
startPage = 1;
endPage = totalPages;
} else {
// Se tiver mais de 10 páginas totais, calcular as páginas inicial e final
if (currentPage <= 6) {
startPage = 1;
endPage = 10;
} else if (currentPage + 4 >= totalPages) {
startPage = totalPages - 9;
endPage = totalPages;
} else {
startPage = currentPage - 5;
endPage = currentPage + 4;
}
}
// Cálculo de índices de itens iniciais e finais
let startIndex = (currentPage - 1) * pageSize;
let endIndex = Math.min(startIndex + pageSize - 1, totalItems - 1);
// Criar um array de páginas para o ng-repeat no componente
let pages = _.range(startPage, endPage + 1);
// Retornar objeto com todas as propriedades exigidas para exibição
return {
totalItems: totalItems,
currentPage: currentPage,
pageSize: pageSize,
totalPages: totalPages,
startPage: startPage,
endPage: endPage,
startIndex: startIndex,
endIndex: endIndex,
pages: pages,
};
}
}
AppComponent que usa o serviço Pager
Um exemplo de componente angular 2 que usa o Pager Service acima para paginar uma lista de itens fictícios que são extraídos de um arquivo json no servidor.
import { Component, OnInit } from '@angular/core';
import { Http, Headers, RequestOptions, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import * as _ from 'underscore';
import { PagerService } from './_services/index';
@Component({
moduleId: module.id,
selector: 'app',
templateUrl: 'app.component.html',
})
export class AppComponent implements OnInit {
constructor(private http: Http, private pagerService: PagerService) {}
// array com todos os itens a serem paginados
private allItems: any[];
// pager object
pager: any = {};
// items paginados
pagedItems: any[];
ngOnInit() {
// pega os arquivos
this.http
.get('./dummy-data.json')
.map((response: Response) => response.json())
.subscribe((data) => {
//Definir os itens para a resposta json
this.allItems = data;
//Inicializar na página 1
this.setPage(1);
});
}
setPage(page: number) {
if (page < 1 || page > this.pager.totalPages) {
return;
}
// pega o objeto pager do serviço
this.pager = this.pagerService.getPager(this.allItems.length, page);
// pega a página atual de itens
this.pagedItems = this.allItems.slice(
this.pager.startIndex,
this.pager.endIndex + 1
);
}
}
import { Component, OnInit } from '@angular/core';
import { Http, Headers, RequestOptions, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import * as _ from 'underscore';
import { PagerService } from './_services/index';
@Component({
moduleId: module.id,
selector: 'app',
templateUrl: 'app.component.html',
})
export class AppComponent implements OnInit {
constructor(private http: Http, private pagerService: PagerService) {}
// array com todos os itens a serem paginados
private allItems: any[];
// pager object
pager: any = {};
// items paginados
pagedItems: any[];
ngOnInit() {
// pega os arquivos
this.http
.get('./dummy-data.json')
.map((response: Response) => response.json())
.subscribe((data) => {
//Definir os itens para a resposta json
this.allItems = data;
//Inicializar na página 1
this.setPage(1);
});
}
setPage(page: number) {
if (page < 1 || page > this.pager.totalPages) {
return;
}
// pega o objeto pager do serviço
this.pager = this.pagerService.getPager(this.allItems.length, page);
// pega a página atual de itens
this.pagedItems = this.allItems.slice(
this.pager.startIndex,
this.pager.endIndex + 1
);
}
}
HTML Template com itens paginados e navegação
Um exemplo de modelo angular 2 que mostra uma lista de itens paginados e os links de paginação para navegar entre páginas.
<div>
<div class="container">
<div class="text-center">
<h1>Angular 2 - Lógica de Paginação</h1>
<!-- Itens sendo paginados -->
<div *ngFor="let item of pagedItems">{{item.name}}</div>
<!-- Paginação -->
<ul *ngIf="pager.pages && pager.pages.length" class="pagination">
<li [ngClass]="{disabled:pager.currentPage === 1}">
<a (click)="setPage(1)">Início</a>
</li>
<li [ngClass]="{disabled:pager.currentPage === 1}">
<a (click)="setPage(pager.currentPage - 1)">Anterior</a>
</li>
<li
*ngFor="let page of pager.pages"
[ngClass]="{active:pager.currentPage === page}"
>
<a (click)="setPage(page)">{{page}}</a>
</li>
<li [ngClass]="{disabled:pager.currentPage === pager.totalPages}">
<a (click)="setPage(pager.currentPage + 1)">Próximo</a>
</li>
<li [ngClass]="{disabled:pager.currentPage === pager.totalPages}">
<a (click)="setPage(pager.totalPages)">Último</a>
</li>
</ul>
</div>
</div>
</div>
<div>
<div class="container">
<div class="text-center">
<h1>Angular 2 - Lógica de Paginação</h1>
<!-- Itens sendo paginados -->
<div *ngFor="let item of pagedItems">{{item.name}}</div>
<!-- Paginação -->
<ul *ngIf="pager.pages && pager.pages.length" class="pagination">
<li [ngClass]="{disabled:pager.currentPage === 1}">
<a (click)="setPage(1)">Início</a>
</li>
<li [ngClass]="{disabled:pager.currentPage === 1}">
<a (click)="setPage(pager.currentPage - 1)">Anterior</a>
</li>
<li
*ngFor="let page of pager.pages"
[ngClass]="{active:pager.currentPage === page}"
>
<a (click)="setPage(page)">{{page}}</a>
</li>
<li [ngClass]="{disabled:pager.currentPage === pager.totalPages}">
<a (click)="setPage(pager.currentPage + 1)">Próximo</a>
</li>
<li [ngClass]="{disabled:pager.currentPage === pager.totalPages}">
<a (click)="setPage(pager.totalPages)">Último</a>
</li>
</ul>
</div>
</div>
</div>
O projeto está disponível no GitHub em github.com/cornflourblue/angular2-pagination-example
Referências
- Blog do Jason Watmore - Angular 2 - Pagination Example with Logic like Google
- Documentação do Angular 2 - Angular docs
Formatação de datas no Jekyll
Introdução ao NestJS: Como acelerar o desenvolvimento de backend Node.js