programing

Angular Mat Paginator가 초기화되지 않음

bestprogram 2023. 9. 24. 13:03

Angular Mat Paginator가 초기화되지 않음

저는 두 가지 구성요소가 있습니다.둘 다 매트 테이블과 페이지 표시기가 있고 페이지 표시기는 한 구성 요소에 대해 작동하고 코드는 비슷하지만 다른 구성 요소에는 작동하지 않습니다.아래는 저의 html 입니다.

<div class="mat-elevation-z8">
    <mat-table [dataSource]="dataSource" matSort>
        <ng-container matColumnDef="col1">
            <mat-header-cell *matHeaderCellDef mat-sort-header> Column1 </mat-header-cell>
            <mat-cell *matCellDef="let row"> {{row.col1}} </mat-cell>
        </ng-container>

        <ng-container matColumnDef="col2">
            <mat-header-cell *matHeaderCellDef mat-sort-header> Column2 </mat-header-cell>
            <mat-cell *matCellDef="let row"> {{row.col2}} </mat-cell>
        </ng-container>

        <!-- Different columns goes here -->

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

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

그리고 아래는 component.ts에 있는 제 코드입니다.

dataSource: MatTableDataSource<any>;
displayedColumns = ['col1', 'col2', ... ];

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

ngOnInit(): void {
    // Load data
    this.dataSource = new MatTableDataSource(somearray);
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
}

다른 구성 요소에 대해서도 유사한 코드가 작동하고 있고 페이지가 제대로 표시된 테이블이 렌더링되고 있습니다. 이 코드에 무슨 문제가 있는지 전혀 알 수 없습니다.

어떤 도움이라도 주시면 정말 감사하겠습니다.

에는.<mat-paginator>.*ngIf데이터가 비동기적으로 로드될 때까지 렌더링되지 않았습니다.원인이 있습니다.this.paginator되려고undefined에 있어서도ngAfterViewInit . 합니다(으)로 자동 합니다.MatTableDataSource다를 하는 데 .paginator.undefined.

은 이었습니다.<mat-paginator> 밖에*ngIf

이것이 저와 같은 처지에 있는 사람에게 도움이 되길 바랍니다.

저는 비슷한 문제를 해결하기 위해 인스턴스를 타임아웃으로 둘러싸았습니다.시도해 보기:

setTimeout(() => this.dataSource.paginator = this.paginator);

선택한 답변이 효과가 있고 문제를 해결할 수 있지만 여전히 해결해야 할 문제입니다.이것은 그 문제를 다루는 적절하고 우아한 방법입니다.

해 보십시오.AfterViewInit를 넣고,에를 넣습니다.this.dataSource.paginator = this.paginator에서 안에ngAfterViewInit()

    ngAfterViewInit() {
        this.dataSource.paginator = this.paginator
    }

입니다 것입니다.setTimeout.

각7+ (8/9/10/11/12) 그 문제를 해결하는 또 다른 우아한 해결책이 있습니다.

쇼트 버전

ChangeDetectorRef.detectChanges().

롱 버전

1단계:

ChangeDetectorRef&&

import { ..., ChangeDetectorRef } from '@angular/core';
import { MatSort, MatTableDataSource, MatPaginator } from '@angular/material';

2단계:

구성 요소에 클래스 속성 설정

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

3단계:

ChangeDetectorRef

constructor (..., private cdr: ChangeDetectorRef, ...) { ... }

4단계:

detectChanges()

this.dataSource = new MatTableDataSource (MY_DATA);
this.cdr.detectChanges();

선택적 단계:

그 다음에는 다음과 같은 다른 속성을 설정할 수 있습니다.

this.dataSource.sort = this.sort;
this.dataSource.paginator = this.paginator;

이 때문에.paginator가 이.dataSource.paginator에 할당할 시점에 정의되지 않았습니다.

정적 데이터를 사용하면 작동합니다.

 @ViewChild(MatPaginator, {static: false}) paginator: MatPaginator; // For pagination
 @ViewChild(MatSort, {static: false}) sort: MatSort; // For Sort

 ngOnInit(): void {
   this.dataSource.data = this.dataList; // Data list is data array 
 }

 ngAfterViewInit(): void {
   this.dataSource.paginator = this.paginator; // For pagination
   this.dataSource.sort = this.sort; // For sort
 }

동적 데이터(Data from API)를 사용하면 작동합니다.

페이지화용

  @ViewChild(MatPaginator, {static: false})
  set paginator(value: MatPaginator) {
    if (this.dataSource){
      this.dataSource.paginator = value;
    }
  }

정렬용

  @ViewChild(MatSort, {static: false})
  set sort(value: MatSort) {
    if (this.dataSource){
      this.dataSource.sort = value;
    }
  }

참고로 나는 무브먼트에서 Angular 9를 사용합니다.

1차 솔루션

*ngIfdiv 내부에서 외부로 매트파기네이터 이동

두번째 해결책

MatPaginator 또는 MatSort를 선언하는 동안 static false 사용

@ViewChild(MatPaginator, {static: false}) paginator: MatPaginator;
@ViewChild(MatSort, {static: false}) sort: MatSort;

페이지 표시기를 뷰에서 사용할 수 있고 데이터 소스에 검색 및 연결할 수 있는 경우 문제는 이 문제의 주요 핵심이자 일반적인 함정입니다. 방법에는다를 하는 것이 됩니다.setTimeout()그리고.ngAfterViewInit이다 - "" 의을 확실히 해결 @ViewChild구성 요소 필드를 올바른 페이지 표시기 값으로 설정했습니다."

은 입니다.@ViewChild속성 설정자에게 해당 설정자가 유효한 페이지 표시자와 함께 호출되는 즉시(그리고 자주) 데이터 소스 페이지 표시자를 설정합니다.

데이터 모든 이 본 (처럼) 것도 합니다.data

 <mat-table [dataSource]="dataSource" matSort>

      <ng-container matColumnDef="col1">
        <mat-header-cell *matHeaderCellDef mat-sort-header> Column1 </mat-header-cell>
        <mat-cell *matCellDef="let row"> {{row.col1}} </mat-cell>
      </ng-container>

      <ng-container matColumnDef="col2">
        <mat-header-cell *matHeaderCellDef mat-sort-header> Column2 </mat-header-cell>
        <mat-cell *matCellDef="let row"> {{row.col2}} </mat-cell>
      </ng-container>

      <!-- additional columns go here -->

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

    <mat-paginator #scheduledOrdersPaginator [pageSizeOptions]="[5, 10, 20]"></mat-paginator>
  </div>
dataSource: MatTableDataSource<any> = new MatTableDataSource();
displayedColumns = ['col1', 'col2', ... ];

@ViewChild('scheduledOrdersPaginator') set paginator(pager:MatPaginator) {
  if (pager) this.dataSource.paginator = pager;
}

@ViewChild(MatSort) set sort(sorter:MatSort) {
  if (sorter) this.dataSource.sort = sorter;
}

ngOnInit(): void {
    this.loadData().subscribe(somearray => { this.dataSource.data = somearray; });
}

이 방식은 (한) 있을 때에 있는 중 한 를해야 합니다.*ngIf- 매우 됩니다.e -됩니다.

작동하려면 데이터를 원본에서 가져온 후에 페이지 표시기를 설정해야 했습니다.

getVariables() {
    this.activeRoute.params.subscribe(params => {
        if (params['id'] && (params['type'] === Type.CodeList)) {
            this.dataService
                .getItems(this.currentLanguage, params['id'])
                .subscribe((items: any) => {
                    this.dataSource.data = this.items;
                    this.dataSource.paginator = this.paginator;
                })
        }
    })
}

그걸 알아내는데 몇 시간이 걸렸습니다.

은 입니다.this.dataSource = new MatTableDataSource<MyInterface>(Object.values(data));tthis.dataSource.paginator = this.paginator;

사용하고 있었습니다.this.dataSource = data데이터를 얻을 수는 있었지만 페이지가 작동하지 않았습니다.

를 .new MatTableDataSource

각도 11에서 작동합니다.

제가 찾은 해결책은 데이터가 성공적으로 로드된 후에 페이지네이터를 설정하는 것입니다.

this._empService.GetEmpList().subscribe(
  data => {
    this.empListDataSource = new MatTableDataSource<empToShow>(Object.values(data))
    this.empListDataSource.paginator = this.paginator
  }
)

위에 제시된 모든 솔루션을 사용해 본 결과, 간단한 솔루션이 효과를 발휘했습니다.누가 막혔는지 참고로 글을 올립니다.

Angular 8을 쓰고 있습니다.하위 참조에 {static: false}만 추가하면 됨

  @ViewChild(MatSort, { static: false }) sort: MatSort;
  @ViewChild(MatPaginator, {static: false}) paginator: MatPaginator;

여기서 솔루션 제공

나는 이것을 사용했습니다.

@ViewChild(MatSort, {읽기: true, static: false}) 정렬: MatSort;

@ViewChild(MatPaginator, {읽기: true, static: false }) 패기네이터:매트 피기네이터;

위의 어떤 해결책도 저에게 효과가 없었습니다.

this.paginator에 표시될 그렇기 다. 그래서 일부 인플레이스에서setTimeout해결책이 통합니다.

제 제 있었어요ngIf다 되었습니다.ngIf는 true만을 하는).다.this.dataSource.paginator = this.paginator위에ngOnInit

이 만 하는 것입니다. 사실은 테이블이 그 때에만 로딩되도록 하는 것입니다.this.dataSource.paginator = this.paginator

과 했습니다를 할했습니다.ngIf 됩니다.true합니다를 합니다.

     initPaginator(){
        this.dataSource.paginator = this.paginator
}

꽤 작동하지 '이지만, ( 이었습니다 이 되었습니다.refreshDataScource()'에서 말입니다.ngAfterViewInit()뿐만 아니라 서버가 새로운 데이터로 응답할 때마다. 고칩니다.dataSource피그니처와 그 부류와 함께요다음과 같은 경우:

refreshDataSource() {
    this.dataSource = new MatTableDataSource(myDataArray);
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
  }

그것은 피기네이터와 소트를 고쳤습니다.이제 모든 것이 완벽하게 작동합니다.하지만 저는 이것이 단지 해결책인지 아니면 진짜 해결책인지 잘 모르겠습니다.

setTimeOut()을 사용하면 일시적으로 문제가 해결되지만, 엄청난 양의 데이터 [1000 행]를 MatDataSource에 밀어넣으면 다시 작동하지 않습니다.

데이터 소스 페이지를 설정하기 전에 큰 데이터 세트를 설정하면 매트 테이블의 로딩 속도가 매우 느리다는 것을 확인했습니다.

ngOninit(){
// initialize dataSource here
}
    ngAfterViewInit() {
  this.dataSource.sort = this.sort;
  this.dataSource.paginator = this.paginator;

  /* now it's okay to set large data source... */
  this.dataSource.data = [GetLargeDataSet];}

데이터 소스에 데이터를 밀어 넣기 전에 먼저 데이터 소스를 초기화하고 "Paginator" 또는 "Sort"와 같은 속성을 설정합니다.

Lonely가 ChangeDetectorRef와 관련하여 제안한 것을 구현하고, @ViewChild에 static: false로 객체를 설정하는 것이 효과적이었습니다.

  @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator;
@ViewChild(MatPaginator, {static: false}) paginator: any // For pagination
@ViewChild(MatSort, {static: false}) sort: any; // For Sort

이와 같이 사용하면 문제가 해결됩니다.

가장 많은 투표를 받은 답변이 언급하듯이, 이는 *ngif:

솔루션:

  1. *ngIf 조건에서 매트 파기네이터를 빼냅니다.

  2. *ngIf 조건을 필요에 맞는 다른 조건으로 변경합니다.

    2.1 [숨김]="조건부"로 대체할 수 있습니다.

    2.2 [ngClass]='d-none': conditional'을 사용하여 display: none을 포함하는 클래스를 만들 수도 있습니다.

다른 것들도 있지만 개인적으로 이런 불편함이 있을 때 사용하는 것은 2.2입니다.

  <mat-paginator
        #scheduledOrdersPaginator
          (page)="pageEvent($event)">
        </mat-paginator>
         pageEvent(event){
         //it will run everytime you change paginator
           this.dataSource.paginator = this.paginator;
          }

이 작업은 몇 시간이 걸려야 비로소 제 테이블이 작동하지 않는 이유를 파악할 수 있었습니다.console.logs()를 배치하면 이벤트 순서와 지속적으로 작동하지 않는 이유를 파악하는 데 도움이 되었습니다.제 시나리오는 동적 데이터 소스를 사용한 위의 원래 문제와 비슷했지만 약간 달랐습니다.저는 각진 앱을 처음 새로 고치면 파기네이터 상태가 설정되고 테이블에 대한 데이터가 설정됩니다.이러한 이벤트가 이 순서대로 발생할 경우 예상한 대로 페이지 표시기가 작동했습니다.

테이블에 대한 데이터를 가져오는 데 ReplaySubjects를 사용했기 때문에 페이지 표시기 상태가 ngAfterView(ngAfterView(ngAfterView)Init 후 테이블 데이터가 구독에서 수신됩니다(사용자 ID에 따라 달라지므로 초기값이 없으므로 BehaviorSubjects를 사용하지 않았습니다).문제는 앱의 다른 구성 요소로 이동한 후 동적 테이블 데이터 소스로 돌아갈 때 테이블 데이터가 페이지네이터 상태 이전에 설정된다는 것이었습니다.이렇게 하면 페이지 표시기에 x 페이지가 표시되지만 표시되는 데이터는 항상 데이터의 첫 페이지가 됩니다.

이 성가신 문제를 해결하려면 다음과 같이 하십시오.

  1. 위에 언급한 사용자와 같이 테이블 데이터를 설정하는 간단한 함수 작성:
  setTableData() {
    // set table data
    this.tableData.data = this.images.filter(img => this.filterData(img));

    // some other code below
    ....
  }
  1. 내 구성요소에 두 개의 플래그를 추가했습니다. 하나는 테이블 데이터를 로드한 경우이고 하나는 내 페이지 상태가 설정된 경우입니다.이렇게 하면 데이터 이전에 페이지 설정 상태를 확인할 수 있습니다.
  // initialize our data source for our table and set flags for state
  tableData = new MatTableDataSource<IImage>(this.images);
  loading = true;
  setPageState = false;
  1. AfterView에서 시간 초과 설정을 추가했습니다.ngAfterView 이전에 테이블 데이터가 전달된 경우에만 내 페이지네이터 상태를 설정하고 테이블 데이터를 설정하는 InitInit이 호출되었습니다.setTimeout은 성가신 "값이 확인된 후 변경된 식" 오류를 방지합니다.
  ngAfterViewInit() {
    // add pagination state to our table
    setTimeout(() => {
      console.log('Set paginator state');
      this.setPageState = true;
      this.paginator.pageIndex = this.state.pageIndex;

      // check if we are not loading data, meaning the table came in first so
      // we need to set the data here
      if (!this.loading) {
        this.setTableData();
      }
    }, 0);
  }
  1. 마지막으로 데이터를 구독하는 ngOnInit에서는 paginator 상태를 먼저 설정하지 않는 한 테이블 데이터를 설정하지 않습니다.
  ngOnInit() {
    console.log('ngOnInit');
    this.tableData.sort = this.sort;
    this.tableData.paginator = this.paginator;

    // listen for data
    this.dbService.images.subscribe(images => {
      console.log('Data subscription');
      // save images
      this.images = images;

      // only set table data if paginator state has been set, otherwise it doesnt work
      if (this.setPageState) {
        this.setTableData();
      }

      // hide spinner and update that we have data
      this.loading = false;
    });

    // other code
    .....
  }

그리고 이를 통해 애플리케이션에 처음 로그인할 때와 다른 페이지로 이동하고 동적 테이블로 돌아갈 때에 대해 페이지가 마침내 일관되게 작동했습니다.

변하기만

dataSource: MatTableDataSource<any>;

위해서

dataSource = new MatTableDataSource();
dataSource = new MatTableDataSource();
displayedColumns = ['col1', 'col2', ... ];
@ViewChild('scheduledOrdersPaginator') paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
ngOnInit(): void {
    // Load data
    this.dataSource = new MatTableDataSource(somearray);
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
}

setTimeout()을 사용하는 것은 테이블을 로드하는 데 시간이 얼마나 걸릴지 알 때만 사용 가능한 솔루션입니다.문제는 테이블에 *ngIf를 사용한다는 것입니다(!isLoading 포함).

this.dataSource = new MatTableDataSource(this.rawData);

this.initPaginator();

this.isLoading = false;

이 수정은 변경 탐지 후에만 myisLoading 변수를 false로 설정하고 페이지네이터를 초기화하는 중이었습니다.

this.dataSource = new MatTableDataSource(this.rawData);

this.isLoading = false;

this.cdr.detectChanges();

this.initPaginator();

따라서 데이터를 로드합니다. 표 ->에 해당 페이지의 변경 사항 ->을 감지하는 것으로 표시됩니다.누구에게나 도움이 되었으면 좋겠습니다!

표의 데이터를 페이지화하려면 다음을 추가합니다.<mat-paginator>

테이블의 데이터 소스에 MatTableDataSource를 사용하는 경우 데이터 소스에 MatPaginator를 제공하기만 하면 됩니다.사용자가 변경한 페이지를 자동으로 듣고 올바른 페이지 데이터를 테이블로 전송합니다.

그렇지 않으면 데이터를 페이지화하기 위해 로직을 구현하는 경우 페이지의 출력을 듣고 올바른 데이터 조각을 테이블에 전달할 수 있습니다.

<mat-paginator> inator 페이지 합니다를 합니다.

MatPaginator는 테이블의 데이터를 페이지화하는 데 제공되는 하나의 솔루션이지만 유일한 옵션은 아닙니다.실제로 MatTable과 그 인터페이스가 특정 구현에 연결되어 있지 않기 때문에 테이블은 사용자 지정 페이지 UI 또는 전략과 함께 작동할 수 있습니다.

@ViewChild(MatPaginator, {static: true}) paginator: MatPaginator;
ngOnInit() {
  this.dataSource.paginator = this.paginator;
}

https://material.angular.io/components/table/overview 도 참조

의 경우 7을 read매트 페이지네이터 의 인수입니다.

@ViewChild(MatPaginator, {read: true}) paginator: MatPaginator;

저한테는 효과가 있었어요

이것은 동적으로 로드된 테이블 데이터에 적용됩니다.

  private paginator: MatPaginator;
  private sort: MatSort;

  @ViewChild(MatSort) set matSort(ms: MatSort) {
   this.sort = ms;
   this.setDataSourceAttributes();
  }

  @ViewChild(MatPaginator) set matPaginator(mp: MatPaginator) {
   this.paginator = mp;
   this.setDataSourceAttributes();
  }

  setDataSourceAttributes() {
   if(this.dataSource !== undefined){
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
   }
  }

도 와 mat-paginator이 있는 ngIf.

저에게 도움이 된 것은 다음과 같은 코멘트뿐이었습니다.

감사합니다. 이것이 제게 해결책이었습니다.ngIf 대신 [숨김]을 사용하여 페이지네이터가 데이터가 없더라도 렌더링되지만 사용자에게 표시되지 않도록 선택했습니다 – TabsNotSpaces

제가 한 은 을 만든 입니다.div , 에, 와 함께[hidden]=<negation_of_the_same_condition_as_the_ngIf>.

동일한 문제가 있었습니다(테이블 데이터가 표시되는데 Mat Paginator가 작동하지 않습니다).제 경우 "새로운 MatTableDataSource"를 만드는 것을 잊어버렸습니다.

this.dataSource = somearray;

MatPaginator를 사용하는 this.dataSource = new MatTableDataSource(somearray);다입니다.

자료 문서에서 발췌

"Angular Material 라이브러리에는 데이터 배열을 정렬, 페이지화 필터링할있는 테이블의 사용 사례를 단순화하기 위해 현재 테이블 상태에 따라 렌더링할 행을 결정하는 논리를 이미 구현한 MatTableDataSource가 포함되어 있습니다."

이 대답이 누군가에게 도움이 되기를 바랍니다.

ngOnInit() 안에서 비동기 대기를 사용하면 페이지네이터와 소트가 대기해야 합니다!

   @ViewChild(MatPaginator) paginator: MatPaginator;
   @ViewChild(MatSort) sort: MatSort; 
    .
    .
    .
   ngOnInit() {
    this.isLoading = true;
    this._statsService.getAllCampgrounds().subscribe(
      async (response) => {
        this.allCampgrounds = response.allCampgrounds;
        this.dataSource = await new MatTableDataSource(this.allCampgrounds);
        
        this.dataSource.paginator = this.paginator;
        this.dataSource.sort = this.sort;

        this.isLoading = false;
      },
      (error) => {
        this.isLoading = false;
        console.log(error);
      }
    );
  }

위에 게시된 답변자들 중 이 사건에 대해 도움이 된 사람은 아무도 없습니다.

나의 페이지가 제대로 작동하지 않은 이유는 수입 때문입니다.

예를 들면

import {MatPaginator} from "@angular/material/paginator";

작동하지 않아 이 컴포넌트 가져오기를 다음으로 변경했습니다.

import { MatTableDataSource, MatPaginator, MatSort } from '@angular/material';

매트 피너가 있는 매트 테이블이 두 개 있는데 그 중 하나만 작동해서 비슷한 문제가 있었습니다.위의 모든 옵션을 시도한 다음 datasource.data 대신 datasource 개체를 업데이트하고 있다는 것을 깨달았습니다. @Bigeyes가 답변을 공유해 준 덕분에 유형을 업데이트하고 있다는 것을 깨닫지 못했습니다.

테이블 데이터를 로드하지만 페이지네이터가 작동하지 않음:

this.datasource = data.filter(x => (x.planName == this.planName && x.Termed_y == 1))

테이블 로드 데이터 및 페이지네이터 작동:

this.dataSource2.data = data.filter(x => (x.planName == this.planName && x.Termed_y == 1))

하지 않는 setTimeout사용하는 것입니다set:


 @ViewChild(MatPaginator) paginator: MatPaginator;


 set matPaginator(mp: MatPaginator) {
      this.paginator = mp;
      this.dataSource.paginator = this.paginator;
  }

언급URL : https://stackoverflow.com/questions/48785965/angular-matpaginator-doesnt-get-initialized