I have a mat-table that might show up to 5/10/15 entries per page. At first, I had one mat-paginator at the bottom that worked fine. Now I'm being asked to set a paginator at the top and another one at the bottom of the table, so the user won't have to scroll all the way down to reach the paginator if they are looking for an entry that is at the top.
I tried to link both paginator to the same data source. But it didn't worked. So, tried to create 2 datasource, but it also has one limitation.
The only limitation is that the paginator at the bottom can't change items per page, since there isn't a method that lets me control that property.
Also, I couldn't set the page index or items per page properties directly (the table was not refreshing), so all the movements are achieved with some logic and paginator methods like previousPage() or lastPage().
Can anyone help me with this? I'm fine with the solution with either single or multiple datasource.
Working code -> STACKBLITZ
<mat-paginator #paginatorTop (page)="pageEvent = handlePageTop($event)" [length]="length" [pageSizeOptions]="[5, 10, 15]" showFirstLastButtons></mat-paginator>
<mat-paginator #paginatorBottom (page)="pageEvent = handlePageBottom($event)" [length]="length" [pageSizeOptions]="[5, 10, 15]" showFirstLastButtons></mat-paginator>
appponent.ts
ngOnInit() {
this.dataSource2.paginator = this.bottomPaginator;
this.dataSource.paginator = this.topPaginator;
this.topPaginator.length = this.dataSource.data.length;
this.bottomPaginator.length = this.dataSource2.data.length;
}
public handlePageTop(e: any) {
let {pageSize} = e;
this.bottomPaginator.pageSize = pageSize;
if(!this.topPaginator.hasNextPage()){
this.bottomPaginator.lastPage();
}else if(!this.topPaginator.hasPreviousPage()){
this.bottomPaginator.firstPage();
}else{
if(this.topPaginator.pageIndex < this.bottomPaginator.pageIndex){
this.bottomPaginator.previousPage();
} else if(this.topPaginator.pageIndex >this.bottomPaginator.pageIndex){
this.bottomPaginator.nextPage();
}
}
}
public handlePageBottom(e: any) {
if(!this.bottomPaginator.hasNextPage()){
this.topPaginator.lastPage();
}else if(!this.bottomPaginator.hasPreviousPage()){
this.topPaginator.firstPage();
}else{
if(this.bottomPaginator.pageIndex < this.topPaginator.pageIndex){
this.topPaginator.previousPage();
} else if(this.bottomPaginator.pageIndex > this.topPaginator.pageIndex){
this.topPaginator.nextPage();
}
}
}
I have a mat-table that might show up to 5/10/15 entries per page. At first, I had one mat-paginator at the bottom that worked fine. Now I'm being asked to set a paginator at the top and another one at the bottom of the table, so the user won't have to scroll all the way down to reach the paginator if they are looking for an entry that is at the top.
I tried to link both paginator to the same data source. But it didn't worked. So, tried to create 2 datasource, but it also has one limitation.
The only limitation is that the paginator at the bottom can't change items per page, since there isn't a method that lets me control that property.
Also, I couldn't set the page index or items per page properties directly (the table was not refreshing), so all the movements are achieved with some logic and paginator methods like previousPage() or lastPage().
Can anyone help me with this? I'm fine with the solution with either single or multiple datasource.
Working code -> STACKBLITZ
<mat-paginator #paginatorTop (page)="pageEvent = handlePageTop($event)" [length]="length" [pageSizeOptions]="[5, 10, 15]" showFirstLastButtons></mat-paginator>
<mat-paginator #paginatorBottom (page)="pageEvent = handlePageBottom($event)" [length]="length" [pageSizeOptions]="[5, 10, 15]" showFirstLastButtons></mat-paginator>
app.ponent.ts
ngOnInit() {
this.dataSource2.paginator = this.bottomPaginator;
this.dataSource.paginator = this.topPaginator;
this.topPaginator.length = this.dataSource.data.length;
this.bottomPaginator.length = this.dataSource2.data.length;
}
public handlePageTop(e: any) {
let {pageSize} = e;
this.bottomPaginator.pageSize = pageSize;
if(!this.topPaginator.hasNextPage()){
this.bottomPaginator.lastPage();
}else if(!this.topPaginator.hasPreviousPage()){
this.bottomPaginator.firstPage();
}else{
if(this.topPaginator.pageIndex < this.bottomPaginator.pageIndex){
this.bottomPaginator.previousPage();
} else if(this.topPaginator.pageIndex >this.bottomPaginator.pageIndex){
this.bottomPaginator.nextPage();
}
}
}
public handlePageBottom(e: any) {
if(!this.bottomPaginator.hasNextPage()){
this.topPaginator.lastPage();
}else if(!this.bottomPaginator.hasPreviousPage()){
this.topPaginator.firstPage();
}else{
if(this.bottomPaginator.pageIndex < this.topPaginator.pageIndex){
this.topPaginator.previousPage();
} else if(this.bottomPaginator.pageIndex > this.topPaginator.pageIndex){
this.topPaginator.nextPage();
}
}
}
Share
Improve this question
edited Apr 3, 2020 at 14:20
UI_Dev
asked Apr 3, 2020 at 14:07
UI_DevUI_Dev
3,42718 gold badges53 silver badges93 bronze badges
3
- Maybe u can upload your code to StackBlitz ?! – Baruch Mashasha Commented Apr 3, 2020 at 14:17
- Yes, its there in the question itself. stackblitz./edit/multiple-paginators-knhf4q – UI_Dev Commented Apr 3, 2020 at 14:20
- issue is not with the design bro, its with the bottom pagination items per page size. data source is not updating – UI_Dev Commented Apr 3, 2020 at 15:18
2 Answers
Reset to default 8 +500No need to use two paginators made some changes in your code, please check it.
Here is my stackblitz code :- https://stackblitz./edit/multiple-paginators-svwwfj
Hope this helps!
This solution works if you want to show one paginator at a time
To solve the above problem, I created a directive scroll-to. In this directive i listened for scroll events and pared the window.pageYOffset
with element's nativeElement.offsetTop
if (pageYOffset of window < element's offsetTop)
im was setting the property showUpperOne
true else property showLowerOne
true.
import {Directive,HostListener,ElementRef} from '@angular/core'
@Directive(
{
selector:"[scrolledTo]",
exportAs:"scrolledTo"
}
)
export class ScrollDirective {
showUpperOne=true;
showLowerOne=false;
constructor(private el:ElementRef){}
@HostListener("window:scroll",['$event'])
onScroll(){
const elementPosition = this.el.nativeElement.offsetTop;
const scrollPosition = window.pageYOffset;
this.showUpperOne=scrollPosition<elementPosition
this.showLowerOne = scrollPosition>= elementPosition;
}
}
I used this directive on div which contains two paginators having the same template reference and one mat table
<div #mainDiv="scrolledTo" scrolledTo class="example-container mat-elevation-z8">
<mat-paginator *ngIf="mainDiv.showUpperOne" #paginator
[pageSize]="currentPageSize"
[pageSizeOptions]="[5, 10, 20]"
(page)="pageEvents($event)"
[showFirstLastButtons]="true">
</mat-paginator>
<mat-table #table [dataSource]="dataSource">...
</mat-table>
<mat-paginator *ngIf="mainDiv.showLowerOne" #paginator
[pageSize]="currentPageSize"
[pageSizeOptions]="[5, 10, 20]"
(page)="pageEvents($event)"
[showFirstLastButtons]="true">
</mat-paginator>
I did set the template reference variable for div #mainDiv="scrolledTo"
and accessed the properties of directive to show and hide paginators *ngIf="mainDiv.showLowerOne
" , *ngIf="mainDiv.showUpperOne"
respectively.
This will show or hide the paginators on scroll but there will be problem with giving the paginator functionality to other paginator once one paginator hides. It has to be set to datasource again.
In order to solve this,i added currentPageSize property and did set the default value as
10 currentPageSize=10;
. In order to reassign the paginator to datasource, i listened for the page events using (page)="pageEvents($event)"
in template of paginator.
and in pageEvents function
pageEvents(event){
this.currentPageSize=event.pageSize;
}
also on scroll
@HostListener("window:scroll",['$event'])
onScroll(){
setTimeout(()=> this.dataSource.paginator = this.paginator,0)
}
Stackblitz: https://stackblitz./edit/angular-nbtcgz