You have an application that uses ngrx to store your data. NgbrxPaginator gives you a really easy way to paginate your data with filters.
This package is in BETA:
- 0.5.0: angular@18, ngrx@18 and ng-bootstrap@17.
- 0.4.0: angular@17, ngrx@17 and ng-bootstrap@16.
The code is rather simple and if you want to join, you are more than welcome.
This package does not deal with backend pagination.
npm i ngbrx-paginator
ngbrx-paginator depends on ngrx and ng-bootstrap.
The following example is extracted from the departement module of the test application.
Suppose you have a departement
[sic] module that has a slice of your store containing all the departments of France. The module provides a departements
component that displays an unpaginated list of the departments:
departements.component.ts
import { Component } from '@angular/core';
import { Observable } from 'rxjs';
import { Departement } from '../departement.model';
import { Store } from '@ngrx/store';
import * as fromStore from '../departement.reducer';
@Component({
selector: 'app-departements',
templateUrl: './departements.component.html',
styleUrls: ['./departements.component.css']
})
export class DepartementsComponent {
collection$: Observable<Departement[]> = this.store.select(fromStore.selectAll);
constructor(
private store: Store<fromStore.State>
) { }
}
departements.component.html
<div class="card">
<div class="card-header sticky-top">
<h3 clas="row">
<span class="col-md">Liste des départements</span>
</h3>
</div>
<div class="card-body">
<div class="list-group">
<div class="list-group-item" *ngFor="let item of collection$ | async">
{{ item.code }} {{ item.nom }}
</div>
</div>
</div>
</div>
First, add the NgbrxPaginatorModule
to your departement.module.ts dependencies:
import * as fromDepartement from './departement.reducer';
import { NgbrxPaginatorModule } from 'ngbrx-paginator';
@NgModule({
[...]
imports: [
[...]
NgbrxPaginatorModule.forFeature({
'Departement/Pagination': // The name of the paginator must be unique for the application.
{
// Optional
filters: { // You can provide more than one filter by paginator.
'Nom': { filter: fromDepartement.byName },
'Code': {
filter: fromDepartement.byCode,
inactivate: true // Optional: not displayed when the page is loaded for the first time.
},
'Régions/COM': {
filter: fromDepartement.byRegion,
values: fromDepartement.selectRegions // Optional: provides an observable of the select values object.
}
},
pageSizeOptions: [10, 20, 30] // Defaults to [5, 10, 25, 100]
}
}),
[...]
],
The object provided to the forFeature static method describes the paginators for this module. Each paginator is an object identified by a unique name in the application with the following properties:
-
filters?
: (optional) an object of type{ [key: string]: { filter, values?, inactivate? } }
.Each filter is identified by a key which will be used as a placeholder for the input or the default value for the select. To each key is associated an object with the following properties:
filter
: a filter function that takes two parameters(items: Data[], query: string)
and returnsData[]
;values
: (optional) a MemoizedSelector. If provided, a HTML select element is displayed with the values instead of the input. The object's type is: { [key: string]: string;[key: number]: string }.inactivate
: (optional) boolean. If set to true the filter is inactivated when the paginator is loaded for the first time.
-
pageSizeOptions?
: (optional) defaults to [5, 10, 25, 100].
You have done the most important part of the job. Now, in your component class, add the attribute key
to specify the name of the paginator, and use NgbrxPaginationService
to paginate/filter your collection:
import { Component } from '@angular/core';
import { Observable } from 'rxjs';
import { Store } from '@ngrx/store';
import * as fromStore from '../departement.reducer';
import { Departement } from '../departement.model';
import { NgbrxPaginatorService } from 'ngbrx-paginator';
@Component({
selector: 'app-departements',
templateUrl: './departements.component.html',
styleUrls: ['./departements.component.css']
})
export class DepartementsComponent {
key = 'Departement/Pagination'; // same as in NgbrxPaginatorModules.forFeature
collection$: Observable<Departement[]> = this.fromDepartement.selectAll;
paginatedCollection$: Observable<Departement[]> = this.paginationService.setPaginator(this.key);
constructor(
private store: Store<fromStore.State>,
// inject NgbrxPaginatorService
private paginationService: NgbrxPaginatorService
) { }
}
Finally, add the ngbrx-paginator
component and the optional ngbrx-paginator-filter-desc
component in your template:
<div class="card">
<div class="card-header sticky-top">
<h3>
Liste des départements
<!-- add (optional) --> <ngbrx-paginator-filter-desc class="right" [key]="key"></ngbrx-paginator-filter-desc>
</h3>
<!-- add --> <ngbrx-paginator [key]="key"></ngbrx-paginator>
</div>
<div class="card-body">
<div class="list-group">
<div class="list-group-item" *ngFor="let item of paginatedCollection$ | async"> <!-- replace collection$ -->
{{ item.code }} {{ item.nom }}
</div>
</div>
</div>
</div>
Voilà ! You now have a paginated list of departements
with filters: