Angular 11 - mat-sort is not working in ng-modal table

516 views Asked by At

mat-sort and paginator is not working in ng-modal table. But outside modal it is working properly. Are there any workaround for this issue?

1

There are 1 answers

4
Eliseo On BEST ANSWER

The problem is that, when you try asign the mat-sort, the mat-sort is not reachable -because really it's not displayed-. You need asign the mat-sort after displayed. If you're using mat-dialog, when you open use a setTimeout(). You can think setTimeout as you say to Angular: "After render, don't forget execute this instructions"

const dialogRef = this.dialog.open(DialogOverviewExampleDialog, {
  width: '250px',
  data: {name: this.name, animal: this.animal}
});
setTimeout(()=>{ //<--here you say to Angular the sort
   this.dataSource.sort = this.sort;
})

If you're using ng-bootstrap modal

open(content) {
    this.modalService.open(content, {ariaLabelledBy: 'modal-basic-title'}).result.then((result) => {
      this.closeResult = `Closed with: ${result}`;
    }, (reason) => {
      this.closeResult = `Dismissed ${this.getDismissReason(reason)}`;
    });
    setTimeout(()=>{ //<--here you say to Angular the sort
       this.dataSource.sort = this.sort;
    })
  }

NOTE: remember that, as the mat-table is not visible all the time the mat-sort ViewChild should be like

@ViewChild(MatSort) sort: MatSort;

NOT use {static true} -static true it's used only if the element is always displayed in the component-

Update really the solution proposed not work. Inside a template the "viewChild are not accesible. So the only I get is create a fool directive

@Directive({
  selector: '[fool]',
  exportAs: 'fool'
})
export class FoolDirective implements OnInit {
  ngOnInit()
  {
    setTimeout(()=>{
      (this.table.dataSource as any).sort=this.sort
    })
  }
  constructor(@Optional() private sort:MatSort,@Optional() private table:MatTable<any>){}
}

So, we only need add this directive to our table

<table mat-table [dataSource]="dataSource"
  matSort fool
  class="mat-elevation-z8">
 ....
</table>

See the [stackblitz][1]

Update2 For add a paginator, the thing is more complex. My idea is improve our directive fool, adding a MatPaginator as Optional and send as output

export class FoolDirective implements OnInit {
  @Output() paginatorLoaded:EventEmitter<MatPaginator>=new EventEmitter<MatPaginator>()
  ngOnInit()
  {
    setTimeout(()=>{
      if (this.table && this.sort)
        (this.table.dataSource as any).sort=this.sort
      if (this.paginator)
        this.paginatorLoaded.emit(this.paginator)
    })
  }
  constructor(@Optional() private sort:MatSort,@Optional() private table:MatTable<any>,@Optional() private paginator:MatPaginator){}
}

Then, the only is, when add the Paginator write

<mat-paginator  fool 
         (paginatorLoaded)="dataSource.paginator=$event"
....>
</mat-paginator>

The only is change the .css adding in styles.css

.cdk-overlay-container {
  z-index: 9000;
}

else the select of number of pages don't show -it is showed, but is under the popup

NOTE: Really I don't like so much these work-around, perhaf is time to re-think and use another popup -e.g. the material- or use the ngb-bootstrap modal with components nor with template. [1]: https://stackblitz.com/edit/angular-hbadro?file=src%2Fapp%2Ffool.directive.ts