2017-12-18 2 views
4

각도 재료 2, MatPaginator 서버 쪽 페이징을 달성하려고합니다. 어떻게 적용합니까?각도 재질 2 테이블 서버 쪽 페이지 매기기

<div class="example-container mat-elevation-z8"> 
    <mat-table #table [dataSource]="dataSource"> 

    <!-- Position Column --> 
    <ng-container matColumnDef="position"> 
     <mat-header-cell *matHeaderCellDef> No. </mat-header-cell> 
     <mat-cell *matCellDef="let element"> {{element.position}} </mat-cell> 
    </ng-container> 

    <!-- Name Column --> 
    <ng-container matColumnDef="name"> 
     <mat-header-cell *matHeaderCellDef> Name </mat-header-cell> 
     <mat-cell *matCellDef="let element"> {{element.name}} </mat-cell> 
    </ng-container> 

    <!-- Weight Column --> 
    <ng-container matColumnDef="weight"> 
     <mat-header-cell *matHeaderCellDef> Weight </mat-header-cell> 
     <mat-cell *matCellDef="let element"> {{element.weight}} </mat-cell> 
    </ng-container> 

    <!-- Symbol Column --> 
    <ng-container matColumnDef="symbol"> 
     <mat-header-cell *matHeaderCellDef> Symbol </mat-header-cell> 
     <mat-cell *matCellDef="let element"> {{element.symbol}} </mat-cell> 
    </ng-container> 

    <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row> 
    <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row> 
    </mat-table> 

    <mat-paginator #paginator 
       [pageSize]="10" 
       [pageSizeOptions]="[5, 10, 20]"> 
    </mat-paginator> 
</div> 

매김 구성 요소 :

import {Component, ViewChild} from '@angular/core'; 
import {MatPaginator, MatTableDataSource} from '@angular/material'; 

/** 
* @title Table with pagination 
*/ 
@Component({ 
    selector: 'table-pagination-example', 
    styleUrls: ['table-pagination-example.css'], 
    templateUrl: 'table-pagination-example.html', 
}) 
export class TablePaginationExample { 
    displayedColumns = ['position', 'name', 'weight', 'symbol']; 
    dataSource = new MatTableDataSource<Element>(ELEMENT_DATA); 

    @ViewChild(MatPaginator) paginator: MatPaginator; 

    /** 
    * Set the paginator after the view init since this component will 
    * be able to query its view for the initialized paginator. 
    */ 
    ngAfterViewInit() { 
    this.dataSource.paginator = this.paginator; 
    } 
} 

export interface Element { 
    name: string; 
    position: number; 
    weight: number; 
    symbol: string; 
} 

const ELEMENT_DATA: Element[] = [ 
    {position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'}, 
    {position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'}, 
    {position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'}, 
    {position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'}, 
    {position: 5, name: 'Boron', weight: 10.811, symbol: 'B'}, 
    {position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C'}, 
    {position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N'}, 
    {position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O'}, 
    {position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F'}, 
    {position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne'}, 
    {position: 11, name: 'Sodium', weight: 22.9897, symbol: 'Na'}, 
    {position: 12, name: 'Magnesium', weight: 24.305, symbol: 'Mg'}, 
    {position: 13, name: 'Aluminum', weight: 26.9815, symbol: 'Al'}, 
    {position: 14, name: 'Silicon', weight: 28.0855, symbol: 'Si'}, 
    {position: 15, name: 'Phosphorus', weight: 30.9738, symbol: 'P'}, 
    {position: 16, name: 'Sulfur', weight: 32.065, symbol: 'S'}, 
    {position: 17, name: 'Chlorine', weight: 35.453, symbol: 'Cl'}, 
    {position: 18, name: 'Argon', weight: 39.948, symbol: 'Ar'}, 
    {position: 19, name: 'Potassium', weight: 39.0983, symbol: 'K'}, 
    {position: 20, name: 'Calcium', weight: 40.078, symbol: 'Ca'}, 
]; 

내가 다음 페이지 클릭이나 페이지 크기 변경의 변경 이벤트를 트리거 할 서버 측 페이지 매김을 달성 할 수있는 방법은 다음

은 코드 예제입니다 다음 레코드 세트를 얻으십시오.

https://stackblitz.com/angular/qxxpqbqolyb?file=app%2Ftable-pagination-example.ts

누구나하시기 바랍니다?

답변

1

각 재료 설명서의 Table retrieving data through HTTP 다음에이 문제가 발생했습니다. 모든에 ngAfterViewInit 덕분에 내부에서 처리 할 것을

import {Component, AfterViewInit, ViewChild} from '@angular/core'; 
import {HttpClient} from '@angular/common/http'; 
import {MatPaginator, MatSort, MatTableDataSource} from '@angular/material'; 
import {Observable} from 'rxjs/Observable'; 
import {merge} from 'rxjs/observable/merge'; 
import {of as observableOf} from 'rxjs/observable/of'; 
import {catchError} from 'rxjs/operators/catchError'; 
import {map} from 'rxjs/operators/map'; 
import {startWith} from 'rxjs/operators/startWith'; 
import {switchMap} from 'rxjs/operators/switchMap'; 

/** 
* @title Table retrieving data through HTTP 
*/ 
@Component({ 
    selector: 'table-http-example', 
    styleUrls: ['table-http-example.css'], 
    templateUrl: 'table-http-example.html', 
}) 
export class TableHttpExample implements AfterViewInit { 
    displayedColumns = ['created', 'state', 'number', 'title']; 
    exampleDatabase: ExampleHttpDao | null; 
    dataSource = new MatTableDataSource(); 

    resultsLength = 0; 
    isLoadingResults = false; 
    isRateLimitReached = false; 

    @ViewChild(MatPaginator) paginator: MatPaginator; 
    @ViewChild(MatSort) sort: MatSort; 

    constructor(private http: HttpClient) {} 

    ngAfterViewInit() { 
    this.exampleDatabase = new ExampleHttpDao(this.http); 

    // If the user changes the sort order, reset back to the first page. 
    this.sort.sortChange.subscribe(() => this.paginator.pageIndex = 0); 

    merge(this.sort.sortChange, this.paginator.page) 
     .pipe(
     startWith({}), 
     switchMap(() => { 
      this.isLoadingResults = true; 
      return this.exampleDatabase!.getRepoIssues(
      this.sort.active, this.sort.direction, this.paginator.pageIndex); 
     }), 
     map(data => { 
      // Flip flag to show that loading has finished. 
      this.isLoadingResults = false; 
      this.isRateLimitReached = false; 
      this.resultsLength = data.total_count; 

      return data.items; 
     }), 
     catchError(() => { 
      this.isLoadingResults = false; 
      // Catch if the GitHub API has reached its rate limit. Return empty data. 
      this.isRateLimitReached = true; 
      return observableOf([]); 
     }) 
    ).subscribe(data => this.dataSource.data = data); 
    } 
} 

export interface GithubApi { 
    items: GithubIssue[]; 
    total_count: number; 
} 

export interface GithubIssue { 
    created_at: string; 
    number: string; 
    state: string; 
    title: string; 
} 

/** An example database that the data source uses to retrieve data for the table. */ 
export class ExampleHttpDao { 
    constructor(private http: HttpClient) {} 

    getRepoIssues(sort: string, order: string, page: number): Observable<GithubApi> { 
    const href = 'https://api.github.com/search/issues'; 
    const requestUrl = 
     `${href}?q=repo:angular/material2&sort=${sort}&order=${order}&page=${page + 1}`; 

    return this.http.get<GithubApi>(requestUrl); 
    } 
} 

봐 : 예, 당신이 필요로하는 테이블에 모든 것을 매김, 정렬 및 기타 물건, 코드를 처리 할 수 ​​ngAfterViewInit() 플러스 관찰 가능한을 사용한다 말한다

관찰 할 수있는. 줄 this.resultsLength = data.total_count;은 귀하의 서비스가 전체 등록 횟수의 데이터를 반환 할 것으로 기대하고 있습니다. 제 경우에는 springboot를 사용하고 있으며 필요한 모든 것을 반환했습니다.

더 자세한 설명이 필요하면 의견을 쓰고 답변을 업데이트하겠습니다. 문서에서 예제를 확인하면됩니다.

+0

서버 측 페이지 매김과 함께 페이지 매거기를 사용하려고하는데 다음 페이지 및 이전 페이지 이벤트를 어떻게 관리합니까? thnx – bre

+0

@bre 이벤트를 컨트롤에 등록하는 방법 이벤트가 발생할 때이를 감지하고 데이터를 새로 고칩니다. –

+0

안녕하세요, 재빨리 재판에 감사하지만 ngxdatatable :-)를 사용하여 끝났습니다. – bre

2

Wilfredo의 답변 (https://stackoverflow.com/a/47994113/986160)을 바탕으로 나는 몇 가지 질문도 빠져 있기 때문에 전체 작업 예제를 작성했습니다. 다음은 일반적인 서버 측 페이지 매김을위한 케이스와 각도 5 재질 디자인을 사용하여 정렬입니다 (아직 필터링을 연결합니다) - 희망 누군가에게 도움이 될 것입니다 :

페이징 구성 요소 :

import { ViewChild, Component, Inject, OnInit, AfterViewInit } from '@angular/core'; 
import { EntityJson } from './entity.json'; 
import { EntityService } from './entity.service'; 
import { MatPaginator, MatSort, MatTableDataSource } from '@angular/material'; 
import { Observable } from 'rxjs/Observable'; 
import { merge } from 'rxjs/observable/merge'; 
import { of as observableOf } from 'rxjs/observable/of'; 
import { catchError } from 'rxjs/operators/catchError'; 
import { map } from 'rxjs/operators/map'; 
import { startWith } from 'rxjs/operators/startWith'; 
import { switchMap } from 'rxjs/operators/switchMap'; 

@Component({ 
    selector: 'entity-latest-page', 
    providers: [EntityService], 
    styles: [` 
     :host mat-table { 
      display: flex; 
      flex-direction: column; 
      min-width: 100px; 
      max-width: 800px; 
      margin: 0 auto; 
     } 
    `], 
    template: 
    `<mat-card> 
     <mat-card-title>Entity List 
     <button mat-button [routerLink]="['/create/entity']"> 
      CREATE 
     </button> 
     </mat-card-title> 
     <mat-card-content> 
      <mat-table #table matSort [dataSource]="entitiesDataSource" matSort class="mat-elevation-z2"> 
       <ng-container matColumnDef="id"> 
        <mat-header-cell *matHeaderCellDef mat-sort-header> Id </mat-header-cell> 
        <mat-cell *matCellDef="let element"> {{element.id}} </mat-cell> 
       </ng-container> 
       <ng-container matColumnDef="name"> 
        <mat-header-cell *matHeaderCellDef mat-sort-header> Name </mat-header-cell> 
        <mat-cell *matCellDef="let element"> {{element.name}} </mat-cell> 
       </ng-container> 
       <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row> 
       <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row> 
      </mat-table> 
     </mat-card-content> 
     <mat-card-content> 
      <mat-paginator #paginator [length]="resultsLength" 
       [pageSize]="5" 
       [pageSizeOptions]="[5, 10, 20]"> 
      </mat-paginator> 
     </mat-card-content> 
    </mat-card> 
    ` 
}) 
export class EntityLatestPageComponent implements AfterViewInit { 

    private entities: EntityJson[]; 
    private entitiesDataSource: MatTableDataSource<EntityJson> = new MatTableDataSource(); 
    private displayedColumns = ['id', 'name']; 

    resultsLength = 0; 
    isLoadingResults = false; 
    isRateLimitReached = false; 

    @ViewChild(MatPaginator) paginator: MatPaginator; 
    @ViewChild(MatSort) sort: MatSort; 

    public constructor(@Inject(EntityService) private entityService: EntityService) { 
    } 

    public ngAfterViewInit() { 

     // If the user changes the sort order, reset back to the first page. 
     this.sort.sortChange.subscribe(() => this.paginator.pageIndex = 0); 
     merge(this.sort.sortChange, this.paginator.page) 
     .pipe(
      startWith({}), 
      switchMap(() => { 
      this.isLoadingResults = true; 
      return this.entityService.fetchLatest(this.sort.active, this.sort.direction, 
        this.paginator.pageIndex + 1, this.paginator.pageSize, 
        (total) => this.resultsLength = total); 
      }), 
      map(data => { 
      this.isLoadingResults = false; 
      this.isRateLimitReached = false; 
      //alternatively to response headers; 
      //this.resultsLength = data.total; 
      return data; 
      }), 
      catchError(() => { 
      this.isLoadingResults = false; 
      this.isRateLimitReached = true; 
      return observableOf([]); 
      }) 
     ).subscribe(data => this.entitiesDataSource.data = data); 
    } 
} 

서비스 :

import { EntityJson } from './entity.json'; 
import { ApiHelper } from '../common/api.helper'; 
import { Http, Headers, Response, RequestOptions } from '@angular/http'; 
import { Inject, Injectable } from '@angular/core'; 
import { Observable } from 'rxjs/Observable'; 
import { AuthenticationService } from '../auth/authentication.service'; 
import { stringify } from 'query-string'; 

@Injectable() 
export class EntityService { 

    private options: RequestOptions; 
    private apiPrefix: string; 
    private apiEndpoint: string; 

    constructor(
     @Inject(Http) private http: Http, 
     @Inject(AuthenticationService) private authService: AuthenticationService) { 

     this.options = authService.prepareRequestHeaders(); 
     this.apiPrefix = 'http://localhost:4200/api/v1/'; 
     this.apiEndpoint = this.apiPrefix + 'entities'; 
    } 

    public fetchLatest(sort: string = '', order: string = '', page: number = 1, perPage: number = 5, initTotal: Function =() => {}): Observable<EntityJson[]> { 
     return this.http.get(this.apiEndpoint +'?' + EntityService.createUrlQuery({sort: {field: sort, order: order}, pagination: { page, perPage }}), this.options) 
      .map((res) => { 
       const total = res.headers.get('x-total-count').split('/').pop(); 
       initTotal(total); 
       return JSON.parse(res.text()).content 
      }); 
    } 

    //should be put in a util 
    static createUrlQuery(params: any) { 
     if (!params) { 
      return ""; 
     } 

     let page; 
     let perPage; 
     let field; 
     let order; 
     let query: any = {}; 
     if (params.pagination) { 
      page = params.pagination.page; 
      perPage = params.pagination.perPage; 
      query.range = JSON.stringify([ 
       page, 
       perPage, 
      ]); 
     } 
     if (params.sort) { 
      field = params.sort.field; 
      order = params.sort.order; 
      if (field && order) { 
       query.sort = JSON.stringify([field, order]); 
      } 
      else { 
       query.sort = JSON.stringify(['id', 'ASC']); 
      } 
     } 
     if (!params.filter) { 
      params.filter = {}; 
     } 
     if (Array.isArray(params.ids)) { 
      params.filter.id = params.ids; 
     } 

     if (params.filter) { 
      query.filter = JSON.stringify(params.filter) 
     } 
     console.log(query, stringify(query)); 
     return stringify(query); 
    } 
} 

,691 363,210

봄 부팅 나머지 컨트롤러 엔드 포인트

@GetMapping("entities") 
public Iterable<Entity> filterBy(
     @RequestParam(required = false, name = "filter") String filterStr, 
     @RequestParam(required = false, name = "range") String rangeStr, @RequestParam(required = false, name="sort") String sortStr) { 
    //my own helpers - for source: https://github.com/zifnab87/react-admin-java-rest 
    //FilterWrapper wrapper = filterService.extractFilterWrapper(filterStr, rangeStr, sortStr); 
    //return filterService.filterBy(wrapper, repo); 
} 

일부 노트 : MatTableModule, 소재 디자인에서 다른 모듈 함께 MatPaginatorModuleMatSortModule :

  1. 는 확인 확실히 당신은 모듈을 가져옵니다.
  2. 스프링 부트 @ControllerAdvice을 통해 채우는 응답 헤더 x-total-count에서 resultsLength (전체)을 채우기로 결정했습니다.또는 EntityService (예 : Page, Spring Boot의 경우)에서 반환 된 객체에서이 정보를 얻을 수 있지만 반환 유형으로 any을 사용해야하거나 프로젝트의 모든 엔티티에 대해 래퍼 클래스 객체를 선언해야 함을 의미하지만 " 유형 안전 ".
관련 문제