1

(Please help, still not resolved)So I am following this stackoverflow(with mat-card) and this(with observable) in combination to try to solve my problem.

I have an observable of an array of objects, and I want to use *ngFor along with mat-card to display them, and then there's a paginator at the very bottom of the page.

Right now, The observables are linked up properly(because it's displaying), but the paginator doesn't seem to show anything(pic), wondering if anyone could help, thank you so much!

(There's a lot of code for other functionalities, so I will try my best to only list out the ones we need, if you feel like there's anything missing please let me know)

HTML:

<div *ngIf="obs| async as objects>
 <div>
  <div>
   <mat-card *ngFor="let ob of objects"> ... </mat-card>
  </div>
  <mat-paginator
  [showFirstLastButtons]="true"
  [pageSizeOptions]="[10, 20, 50, 100]"> 
  </mat-paginator>
 </div>

TS: Side note: filtered$ is the original observable of array I used for the mat-card, now I'm adding paginator, so in HTML you can see I changed to obs

public dataSource = new MatTableDataSource();
@ViewChild(MatPaginator) paginator: MatPaginator;
obs: Observable<any>;
public filtered$: Observable<Array<An Object>>;

constructor(private changeDetectorRef: ChangeDetectorRef){};

ngOnInit(){
...;
  this.filtered$
  .pipe(takeUntil(...))
  .subscribe((arr) => (this.dataSource.data = arr));
 this.changeDetectorRef.detectChanges();
 this.dataSource.paginator = this.paginator;
 this.obs = this.dataSource.connect();
}
Onion
  • 85
  • 1
  • 9
  • Even if I added `[length]="objects.length"`, it is displaying the numbers on the paginator, but the functionalities are not working – Onion Mar 05 '21 at 16:40

2 Answers2

0

you need to use the dataSource on table

or if you want to use without table and dataSource you need to menage the total data on paginator

             <mat-paginator 
                (page)="onPageChange($event)"
                [showFirstLastButtons]="true"
                [length]="total"
                [pageSize]="limit"
                [pageSizeOptions]="[5, 10, 25, 100]">
            </mat-paginator>

where total is total items and limitSize is the number of product for page

corsaro
  • 731
  • 1
  • 9
  • 24
  • Thank you. I don't think you will "need" to use dataSource on table? From one of the links I attached above, one did not use table. And I'm wondering if you could tell me what you did with the `onPageChange($event)` function? And doesn't the "`pageSizeOptions`" determine the "`pageSize`"? – Onion Mar 05 '21 at 16:25
  • @WendyZhang, `pageSizeOptions` does not determine the `pageSize`. Because `pageSize` is the default number of elements you want on a single page. And `pageSizeOptions` are the options to choose from. – Zunayed Shahriar Mar 05 '21 at 16:57
  • Thanks! It seems like the `pageSize` is not the problem here – Onion Mar 05 '21 at 17:59
  • Check out my answer. – Zunayed Shahriar Mar 05 '21 at 18:12
  • @ZunayedShahriar Yeah thanks I did. There are some comments underneath. I'm assuming you are using`*ngFor = pagedDataArray`? But I thought that's not how paginator should work. `*ngFor` should include all elements inside the array. If it doesn't, then my other functionalities won't work... And there are some errors with `Cannot read property 'slice' of null` – Onion Mar 05 '21 at 18:29
  • @WendyZhang, I've said earlier. You need to load all the data first. Then you should filter. – Zunayed Shahriar Mar 05 '21 at 18:32
  • @ZunayedShahriar If I need **all** the data in my html for other purposes what should I do? And could you give me a quick code example to conclude your response? Thank you – Onion Mar 09 '21 at 18:24
  • @WendyZhang You can change the default page size to a large number like 1M. That should do the work and if the users want to see fewer items then they can change the page size from options. Note: Loading too much data in HTML may slow your particular component's performance. – Zunayed Shahriar Mar 10 '21 at 04:54
0

Suggestion: You have to keep separate arrays or observables. One for showing paged data and another to store all the data.

HTML:

<mat-paginator *ngIf="total > 0"
    [length]="total"
    [pageSize]="pageSize"
    [pageIndex]="pageIndex"
    (page)="pageChanged($event)"
    [pageSizeOptions]="[5, 10, 25, 100]">
</mat-paginator>

Note: I think you should not show paginator when you do not have any data.

Typescript:

pageChanged(event: any) {
    this.pageIndex = event.pageIndex;
    this.setFilteredData();
}

setFilteredData() {
    this.yourPagedDataArray = this.yourAllDataArray.slice(this.pageSize * this.pageIndex, this.pageSize * this.pageIndex + this.pageSize);
}

Note: You need to call the setFilteredData() method after your data fetching is completing.

Zunayed Shahriar
  • 2,557
  • 2
  • 12
  • 15
  • Thank you for your response. I'm just wondering about what is the difference between "pagedDataArray" and "allDataArray"? Since now I only have observables, but no raw arrays, how could I use `slice` without using subscribe? – Onion Mar 05 '21 at 17:57
  • And now my understanding is that if `pagedDataArray` is for this current page/s info, while `allDataArray` is for all. But when do I use the `pagedDataArray`? In my HTML, I'm always using the `allDataArray` **observable** – Onion Mar 05 '21 at 18:02