Oi, Marco, tudo bem?
Fico feliz que esteja gostando do curso! Entendo perfeitamente o seu interesse em adicionar paginação à aplicação, pois é um recurso muito útil e comum em projetos reais. Vamos juntos implementar sua sugestão no projeto seguindo as modificações de código abaixo.
Para isso precisamos alterar três arquivos, o livro.service.ts
, lista-livreo.component.html
e lista-livro.component.ts
. O código completo para cada um deles está descrito abaixo:
import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { LivrosResultado } from '../models/interfaces';
@Injectable({
providedIn: 'root'
})
export class LivroService {
private readonly API = 'https://www.googleapis.com/books/v1/volumes';
constructor(private http: HttpClient) { }
buscar(valorDigitado: string, startIndex: number = 0, maxResults: number = 10): Observable<LivrosResultado> {
const params = new HttpParams()
.append('q', valorDigitado)
.append('startIndex', startIndex.toString())
.append('maxResults', maxResults.toString());
return this.http.get<LivrosResultado>(this.API, { params });
}
}
lista-livro.component.ts
:
import { switchMap, map, tap, filter, debounceTime, throwError, catchError, EMPTY, of, BehaviorSubject, combineLatest } from 'rxjs';
import { Component } from '@angular/core';
import { LivroService } from 'src/app/service/livro.service';
import { Item, LivrosResultado } from 'src/app/models/interfaces';
import { LivroVolumeInfo } from 'src/app/models/livroVolumeInfo';
import { FormControl } from '@angular/forms';
const PAUSA = 300;
const RESULTADOS_POR_PAGINA = 10;
@Component({
selector: 'app-lista-livros',
templateUrl: './lista-livros.component.html',
styleUrls: ['./lista-livros.component.css']
})
export class ListaLivrosComponent {
campoBusca = new FormControl();
mensagemErro = '';
livrosResultado: LivrosResultado;
paginaAtual = 0;
private paginaAtualSubject = new BehaviorSubject<number>(0);
constructor(private service: LivroService) { }
livrosEncontrados$ = combineLatest([
this.campoBusca.valueChanges.pipe(
debounceTime(PAUSA),
filter((valorDigitado) => valorDigitado.length >= 3),
tap(() => {
this.paginaAtual = 0;
this.paginaAtualSubject.next(this.paginaAtual);
})
),
this.paginaAtualSubject
])
.pipe(
switchMap(([valorDigitado, paginaAtual]) => this.service.buscar(valorDigitado, paginaAtual * RESULTADOS_POR_PAGINA, RESULTADOS_POR_PAGINA)),
map(resultado => this.livrosResultado = resultado),
tap((retornoAPI) => console.log(retornoAPI)),
map(resultado => resultado.items ?? []),
map((items) => this.livrosResultadoParaLivros(items)),
catchError((erro) => {
console.log(erro)
return throwError(() => new Error(this.mensagemErro = 'Ops, ocorreu um erro. Recarregue a aplicação!'))
})
);
livrosResultadoParaLivros(items: Item[]): LivroVolumeInfo[] {
return items.map(item => {
return new LivroVolumeInfo(item);
});
}
proximaPagina() {
this.paginaAtual++;
this.paginaAtualSubject.next(this.paginaAtual);
}
paginaAnterior() {
if (this.paginaAtual > 0) {
this.paginaAtual--;
this.paginaAtualSubject.next(this.paginaAtual);
}
}
}
lista-livreo.component.html
:
//CÓDIGO OMITIDO
<div>
<button (click)="paginaAnterior()" [disabled]="paginaAtual === 0">Página Anterior</button>
<button (click)="proximaPagina()">Próxima Página</button>
</div>
//CÓDIGO OMITIDO
Além disso, caso queira mais informações sobre como criar paginação em um projeto Angular usando a biblioteca RxJS, você pode ler este artigo. As informações estão em inglês, mas caso queira traduzir, basta clicar com o botão direito do mouse e selecionar a opção "Traduzir para o português".
Espero ter ajudado. Caso tenha dúvidas, conte com o fórum. Abraços!
Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓. Bons Estudos!