Mat Paginator and Sort in ng-bootstrap modal

1.5k Views Asked by At

I am using angular material and ng-bootstrap in my angular 10 project. I am using @ViewChild('historyPaginator') historyPaginator: MatPaginator;for paginator declaration and assigning it to datasource using this.regionHistoryDataSource.paginator = this.historyPaginator;. If I open the mat table in bootstrap modal, pagination doesn't work. Even historyPaginator is coming as undefined.

I tried putting the assignment in ngAfterViewInit but no luck. Any direction here will be appreciated.

My ts file is as below

import { Component, Input, ViewChild } from "@angular/core";
import { MatTableDataSource } from "@angular/material/table";
import { MatPaginator } from "@angular/material/paginator";
import { NgbModal } from "@ng-bootstrap/ng-bootstrap";

@Component({
  selector: "hello",
  templateUrl: "./hello.component.html",
  styles: [
    `
      h1 {
        font-family: Lato;
      }
    `
  ]
})
export class HelloComponent {
  dataSource = new MatTableDataSource<any>();
  data: any;
  @ViewChild("historycontent") historyContent: any;
  @ViewChild("historyPaginator") historyPaginator: MatPaginator;
  displayedColumns: string[] = ["Test1"];
  @Input() name: string;

  constructor(private modalService: NgbModal) {}
  ngOnInit() {
    this.data = [
      {
        Test1: "1"
      },
      {
        Test1: "2"
      }
    ];
  }

  open() {
    this.dataSource = new MatTableDataSource<any>(this.data);
    this.dataSource.paginator = this.historyPaginator;
    this.modalService.open(this.historyContent, {
      backdrop: "static",
      keyboard: false,
      size: "lg"
    });
  }

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

Sample HTML file is

<div>
    <button class="btn btn-outline" (click)="open()">
                                Open</button>
</div>
<ng-template #historycontent let-c="close" let-d="dismiss">
    <div class="modal-header">
        <h4 class="modal-title"><b>Heading</b></h4>
        <button type="button" class="close" aria-label="Close" (click)="d('Cross click')">
            <span aria-hidden="true">&times;</span>
        </button>
    </div>
    <div class="modal-body">
        <div class="row">
            <div class="table-responsive">
                <mat-table [dataSource]="dataSource"
                    class="table table-hover table-striped table-bordered dataTable dtr-inline region-modal">
                    <ng-container matColumnDef="Test1">
                        <mat-header-cell *matHeaderCellDef> Test1 </mat-header-cell>
                        <mat-cell *matCellDef="let element"> {{element.Test1}} </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 #historyPaginator="matPaginator" [pageSizeOptions]="[10, 20, 50, 100]"
                    showFirstLastButtons></mat-paginator>
            </div>
        </div>
    </div>
</ng-template>

Created debugging sample code here

1

There are 1 best solutions below

0
On

The issue seems to be that you can't reference an element with ViewChild if it is rendered inside of the ng-template. Reference. Because, the embedded view is created outside of the component with template, so @ViewChild won't work

But it seems like ng-bootstrap is forcing you to use this ng-template approach with their modals (docs).

Therefore the conclusion is that you cannot assign the paginator to the bootstrap table when it is rendered inside of the ng-template.

I would advise you to use a different type of Modal you can use the Angular material Dialog. Or some other library that doesn't force you to use an ng-template.