web-dev-qa-db-ja.com

Angular MatPaginatorが機能していません

2つのコンポーネントがあります。どちらにもマットテーブルとページネーターがあり、ページネーションは1つのコンポーネントで機能し、他のコンポーネントでは機能しませんが、コードは似ています。以下は私の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;
}

他のコンポーネントでも同様のコードが機能し、ページネーションでテーブルが適切にレンダリングされます。このコードの何が問題なのかはわかりません。

どんな助けも本当に感謝されます

28
Nagendra Varma

インスタンス化をタイムアウトで囲むことにより、同様の問題を解決しました。これを試して :

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

私の場合、<mat-paginator>要素は*ngIfを持つコンテナ内にあり、データが非同期にロードされるまでレンダリングしませんでした。これにより、this.paginatorundefinedであってもngAfterViewInitになります。 MatTableDataSourcepaginatorに設定しても、undefinedに問題はないため、これはサイレントに失敗します。

解決策は、<mat-paginator>*ngIf 'dコンテナの外に移動することでした

うまくいけば、これは私と同じ状況にいる人を助けます。

34
Skylar Brown

選択された答えは機能し、問題を解決しますが、依然として回避策です。これは、問題に対処するための適切でエレガントな方法です。

AfterViewInitインターフェイスをクラスに追加してから、this.dataSource.paginator = this.paginatorngAfterViewInit()メソッド内に配置してください

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

回避策setTimeoutを呼び出す必要はありません。

16
hopsey

データソースを設定した直後にChangeDetectorRef.detectChanges()を呼び出します。

// First import ChangeDetectorRef & Material related stuff
import { ..., ChangeDetectorRef } from '@angular/core';
import { MatSort, MatTableDataSource, MatPaginator } from '@angular/material';

// Set properties in your component
@ViewChild(MatSort) sort: MatSort;
@ViewChild(MatPaginator) paginator: MatPaginator;

// Inject in constructor
constructor (..., private cdr: ChangeDetectorRef, ...) { ... }

// Set data source and invoke detectChanges()
this.dataSource = new MatTableDataSource (MY_DATA);
this.cdr.detectChanges();

// after that you can set other properties like
this.dataSource.sort = this.sort;
this.dataSource.paginator = this.paginator;
6
Lonely

それを機能させるには、データがソースからフェッチされた後にページネータを設定する必要がありました

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;
                })
        }
    })
}
3
Hasse

私はangularとTypeScriptの初心者ですが、同じ問題を抱えた後(ただし、並べ替えが機能しなかったということを除いて)、関数 'refreshDataScource()'とサーバーが新しいデータで応答するたびに、ngAfterViewInit()から呼び出されます。この関数では、ページネータとソートでdataSourceを更新するだけです。このような:

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

ページ付けと並べ替えを修正しました。すべてが完全に機能するようになりました。ただし、それが単なる回避策なのか実際の修正なのかはわかりません。

2
Gefilte Fish

変更のみ

dataSource: MatTableDataSource<any>;

for

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;
}
1
Josean

setTimeOut()を使用すると、問題が一時的に解決されますが、MatDataSourceに大量のデータ(たとえば1000行)をプッシュしている場合、これは再び機能しません。

データソースページネータを設定する前に大きなデータセットを設定すると、MatTableのロードが非常に遅くなることがわかりました。

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」などのプロパティを設定してから、データをソースに「Data」プロパティにプッシュします。

1

私は同じ問題を抱えていました(テーブルデータは表示されますが、MatPaginatorは機能しません)。私の場合、「新しいMatTableDataSource」を作成するのを忘れました

this.dataSource = somearray;

this.dataSource = new MatTableDataSource(somearray);が有効になっている間は、MatPaginatorを有効にしないでください。

素材ドキュメント から抽出

「データの配列をソート、ページ分割、フィルタリングできるテーブルを使用するユースケースを簡素化するために、Angular MaterialライブラリにはMatTableDataSourceは、現在のテーブル状態に従ってどの行をレンダリングするかを決定するロジックを既に実装しています。」

この答えが誰かを助けることを願っています。

1
Su0011

私が見つけた解決策は、データが正常にロードされた後にページネーターを設定することです。

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

app.module.tsMatPaginatorModuleをインポートしたことを確認してください

0
Phoenix404

これにより、テーブルが機能しなかった理由を最終的に追跡して理解するのにhoursかかりました。 console.logs()をいくつか配置することで、イベントの順序と、一貫して機能しない理由を把握することができました。私のシナリオは、動的データソースに関する上記の元の問題と似ていましたが、わずかに異なっていました。私にとっては、最初にangularアプリを更新すると、ページネーターの状態が設定され、次にテーブルのデータが設定されます。これらのイベントがこの順序で発生すると、ページネーターは予想どおりに機能しました。

ReplaySubjectsを使用してテーブルのデータを取得しているため、paginatorの状態がngAfterViewInitに設定され、テーブルデータがサブスクリプションから取得されます(ユーザーIDに依存するため、初期値があり、それがBehaviorSubjectsを使用しなかった理由です。私の問題は、アプリ内の別のコンポーネントに移動して動的テーブルデータソースに戻ると、ページデータがページネーターの状態の前に設定されることでした。これにより、ページネーターはページxを表示しますが、表示されるデータは常にデータの最初のページになります。

この迷惑な問題を修正するには:

  1. 上記の誰かとして私のテーブルデータを設定するための簡単な関数を書きました:
  setTableData() {
    // set table data
    this.tableData.data = this.images.filter(img => this.filterData(img));

    // some other code below
    ....
  }
  1. コンポーネントに2つのフラグを追加しました。1つはテーブルデータをロードした場合、もう1つはページネーション状態が設定されていた場合です。これにより、データの前にページネーション状態が確実に設定されます。
  // initialize our data source for our table and set flags for state
  tableData = new MatTableDataSource<IImage>(this.images);
  loading = true;
  setPageState = false;
  1. NgAfterViewInitにsetTimeoutを追加しました。これにより、ページデータが設定され、テーブルデータが通過した場合にのみテーブルデータが設定されます。before ngAfterViewInitが呼び出されました。 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(データをサブスクライブする場所)で、do notページ名の状態が最初に設定されていない限り、テーブルデータを設定します。
  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
    .....
  }

それで、アプリに初めてログインしたときと、他のページに移動して動的テーブルに戻るときのページネーションが、ようやく一貫して機能しました。

0
Zach

上記のすべてのソリューションを試した後、ようやくシンプルなソリューションが機能しました。誰かが立ち往生した場合、私は参考のために投稿しています。

Angular 8.を使用しています。子参照に{static:false}を追加するだけです

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

ここから解決策を得る

私はこれを使用していました:

@ViewChild(MatSort、{read:true、static:false})sort:MatSort;

@ViewChild(MatPaginator、{read:true、static:false})paginator:MatPaginator;

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

setTimeoutを使用しないソリューションは、setを使用することです。


 @ViewChild(MatPaginator) paginator: MatPaginator;


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

私もこの問題を抱えていました。参照scheduledOrdersPaginatorをpagintaorタグに追加し、@ ViewChildで受信しました。ページネーションの問題を解決しました。以下のコードは他の人を助けるかもしれません。

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;
}

html:

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

私の場合、サービスからのデータは非同期に取得されるため、どちらもngOnInitもngAfterViewInitも使用できません。ngOnChangesは次のように使用します。

ngOnChanges(change: SimpleChanges) {
    if (change.properties) {
      if (this.properties.length > 0) {
        this.dataSource = new MatTableDataSource(this.properties);
        this.dataSource.paginator = this.paginator;
      }
    }
  }

Htmlのmat-table要素の[DataSource]属性をコンポーネントのデータソースプロパティに設定して、データソースがテーブルおよびページネーターと確実にバインドされるようにしてください。

0
danfer

これを確認してください Stackoverflow Answer

HTMLコンポーネントが読み込まれた後(* ngIf)でTypeScriptにページネーターを設定すると、問題が修正されました。

0
shaheer shukur

リンクの説明をここに入力 テーブルのデータをページ分割するには、テーブルの後にaを追加します。

テーブルのデータソースにMatTableDataSourceを使用している場合は、MatPaginatorをデータソースに提供するだけです。ユーザーによって行われたページ変更を自動的にリッスンし、適切なページデータをテーブルに送信します。

それ以外の場合、データをページ分割するロジックを実装している場合は、ページネータ(ページ)の出力をリッスンし、データの適切なスライスをテーブルに渡す必要があります。

の使用と設定の詳細については、mat-paginatorのドキュメントをご覧ください。

MatPaginatorは、テーブルのデータをページ分割するために提供されるソリューションの1つですが、唯一のオプションではありません。実際、MatTableとそのインターフェイスは特定の実装に関連付けられていないため、テーブルはカスタムのページ分割UIまたは戦略で機能します。

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