简体   繁体   中英

Paginate Observable in HTML with Mat-paginator and Mat-option

I'm using angular material and observables to create an async list with mat-paginator and mat-option (instead of using a table, client requirements). I want to paginate this list in HTML but with the observable stream, not using a subscribe and an assignment to an auxiliary array paginated.

Example:

<mat-option *ngFor="let elem of opMvAsync | async">
    <!-- Data printed here -->
</mat-option>
<mat-paginator *ngIf="(opMvAsync | async)?.length > 5" [length]="(opMvAsync | async)?.length" [hidePageSize]="true" [pageSize]="5" (page)="onPageChange($event)"></mat-paginator>

And the TS:

//TS 
  opMvAsync : Observable<Array<Items>>;

ngOnInit() {
  this.opMvAsync = this.service.getItems();
}

I have another example in my app, very similar, but using an auxiliary array:

<!-- HTML-->
<mat-option *ngFor="let elem of lstPaginated">
    <!-- Data printed here -->
</mat-option>
<mat-paginator *ngIf="lstOri.length > 5" [length]="lstOri.length" [hidePageSize]="true" [pageSize]="5" (page)="onPageChange($event)"></mat-paginator>

// TS
lstOri: Array<Items>;
lstPaginated: Array<Items>;

ngOnInit() {
  this.service.getItems().subscribe(r=> {
      this.lstOri= r;
      this.lstPaginated= this.lstOri.slice(0, 5);
  });
}
onPageChange(event: PageEvent) {
    this.lstPaginated= this.lstOri.slice(event.pageIndex * event.pageSize, event.pageIndex * event.pageSize + event.pageSize);
    }

This works fine, but it is quite laborious to have to handle two arrays constantly.

Is there any way to work directly paging the observable? Thanks for your advance.

Edit: What I need is to figure it out the way in which I can paginate the observable that I'm rendering in HTML. My OnPageChange should handle which elements of the observable I display, but I don't know how to do it.

You can solve this problem by following below pattern.

  1. In your service , instead of having a method getItems() , create a variable items$ . And set its value to the get/post method call.
  2. In your component, set opMvAsync equal to service.items$ .
  3. Now in your template, use it with async pipe.

Below is the sample code:

my.service.ts

@Injectable({  providedIn: 'root', })
export class MyService {
  ...
  items$ = this.http.get('some/url/').pipe(...);
  ...
}

app.component.ts

export class AppComponent {
 ...
 public opMvAsync$ = this.service.items$.pipe(...);
 ...
}

app.component.html

<div *ngIf="opMvAsync$ | async as opMvAsync">
  <mat-option *ngFor="let elem of opMvAsync | async">
  <!-- Data printed here -->
  </mat-option>
</div>

This way you can avoid the subscribe/unsubcribe work, as async keyword will take care of it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM