1

I have my HTML code like this:

<div class="mat-elevation-z8" *ngIf="Model">
  <br>
  <mat-form-field class="col-md-3 col-lg-3">
    <input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
  </mat-form-field>


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

    <ng-container matColumnDef="StartTime">
      <th mat-header-cell *matHeaderCellDef mat-sort-header> StartTime </th>
      <td mat-cell *matCellDef="let row" style="width: 15%"> {{row.call_start_time | date:'dd-MM-yyyy HH:mm:ss'}} </td>
    </ng-container>

    <ng-container matColumnDef="Duration">
      <th mat-header-cell *matHeaderCellDef mat-sort-header> Duration </th>
      <td mat-cell *matCellDef="let row"> {{row.call_total_duration}} </td>
    </ng-container>


    <ng-container matColumnDef="CallType">
      <th mat-header-cell *matHeaderCellDef mat-sort-header> CallType </th>
      <td mat-cell *matCellDef="let row" style="width: 5%"> {{row.call_type}} </td>
    </ng-container>

    <ng-container matColumnDef="CLI">
      <th mat-header-cell *matHeaderCellDef mat-sort-header> CLI </th>
      <td mat-cell *matCellDef="let row" style="width: 15%"> {{row.call_cli}} </td>
    </ng-container>

    <ng-container matColumnDef="Campaign">
      <th mat-header-cell *matHeaderCellDef mat-sort-header> Campaign </th>
      <td mat-cell *matCellDef="let row" style="width: 20%"> {{row.call_service_name}} </td>
    </ng-container>
    &nbsp;&nbsp;

    <ng-container matColumnDef="Agent">
      <th mat-header-cell *matHeaderCellDef mat-sort-header> Agent </th>
      <td mat-cell *matCellDef="let row"> {{row.call_agent_id}} </td>
    </ng-container>

    <ng-container matColumnDef="Disposition">
      <th mat-header-cell *matHeaderCellDef mat-sort-header> Disposition </th>
      <td mat-cell *matCellDef="let row" style="width: 20%"> {{row.call_end_type_name}} </td>
    </ng-container>

    <ng-container matColumnDef="Remarks">
      <th mat-header-cell *matHeaderCellDef mat-sort-header> Remarks </th>
      <td mat-cell *matCellDef="let row" style="width: 20%"> {{row.call_remark}} </td>
    </ng-container>

    <ng-container matColumnDef="TransfferedTo">
      <th mat-header-cell *matHeaderCellDef mat-sort-header style="width: 5%"> TransfferedTo </th>
      <td mat-cell *matCellDef="let row" style="width: 5%"> {{row.call_child_callnumber}} </td>
    </ng-container>

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

  <mat-paginator [pageSizeOptions]="[5,10, 25]"></mat-paginator>
</div>

Question I referred: mat-sort not working on mat-table

I've referred some of the questions, but all of them are calling the service on ngOnInit(), but I need to call the service on the ngSubmit() method in my .ts file.

Pagination and sorting are not working. I believe there is a problem with my type script file and it looks like this:

import { Component, OnInit, ViewChild } from '@angular/core';
import { FormControl } from '@angular/forms';
import { Observable } from 'rxjs';
import { startWith, map } from 'rxjs/operators';
import { CampaignService } from 'services/campaign.service';
import { MatPaginator, MatSort, MatTableDataSource } from '@angular/material';



export interface State {
  Name: string;
  Id: number;
}
@Component({
  selector: 'app-logs',
  templateUrl: './logs.component.html',
  styleUrls: ['./logs.component.css']
})
export class LogsComponent implements OnInit {
  dataSource: MatTableDataSource<any>;
  displayedColumns: string[] = ['StartTime', 'Duration', 'CallType', 'CLI', 'Campaign' , 'Agent' , 'Disposition' , 'Remarks' , 'TransfferedTo'];

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

  constructor(private webService: CampaignService) {
  
  }


  FromDate: any;
  ToDate: any;
  Campaign: any;
  Agent: any;
  MobileNumber: any;
  stateCtrl = new FormControl();
  filteredStates: Observable<State[]>;
  Model: any;
  Data: any;
  Result: any;

  private _filterStates(value: string): State[] {
    const filterValue = value.toLowerCase();

    return this.Data.filter(state => state.Name.toLowerCase().indexOf(filterValue) === 0);
  }

  ngOnInit() {

    //this.dataSource = new MatTableDataSource(this.Result);
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
  }



  applyFilter(filterValue: string) {
    this.dataSource.filter = filterValue.trim().toLowerCase();

    if (this.dataSource.paginator) {
      this.dataSource.paginator.firstPage();
    }
  }

  onSubmit(data) {

    const deatails = JSON.stringify({
      FromDate: FromDate,
      ToDate: ToDate,
      Campaign: this.Campaign,
      Agent: data.Agent,
      MobileNumber: data.MobileNumber
    });


    this.webService.CallDetails(deatails)
      .subscribe(
        response => {
          this.Model = response;
          this.Result = this.Model.log
          this.dataSource = new MatTableDataSource( this.Result);
    
        },
        (error) => console.error(error)
      );
   
  }


}

Can anyone point out to me where I'm going wrong? Much thanks in advance.

5 Answers5

3

Unfortunately this is an Angular-thing where ViewChild doesn't catch elements with *ngIf in ngAfterViewInit.

https://github.com/angular/components/issues/8705#issuecomment-377266657

Pragati Dugar
  • 262
  • 3
  • 7
2

this is how I solved the problem just in case anybody need it:

 @ViewChild(MatSort) sort: MatSort;
 
 @ViewChild(MatPaginator) set matPaginator(mp: MatPaginator) {
    this.paginator = mp;
    this.setDataSourceAttributes();
    }
    
 dataSource = new MatTableDataSource();  
 displayedColumns: string[] = ['call_start_time', 'call_agent_login_id', 'call_cli', 'call_service_name', 'call_type', 'Play'];
 
 setDataSourceAttributes() {
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
  }
  
  onSubmit() {

    this.webService.CallDetails(deatails)
      .subscribe(
        response => {
        
          this.Model = response;
          this.Result = this.Model.log;
          this.dataSource = new MatTableDataSource(this.Result);
        },
        
        (error) => console.error(error)
      );

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

  <ng-container matColumnDef="call_start_time" class="text-center">
    <th mat-header-cell *matHeaderCellDef mat-sort-header> StartTime </th>
    <td mat-cell *matCellDef="let row" style="width: 25%"> {{row.call_start_time | date:'dd-MM-yyyy HH:mm:ss'}}
    </td>
  </ng-container>

  <ng-container matColumnDef="call_agent_login_id">
    <th mat-header-cell *matHeaderCellDef mat-sort-header> Agent </th>
    <td mat-cell *matCellDef="let row"> {{row.call_agent_login_id}} </td>
  </ng-container>

  <ng-container matColumnDef="call_cli">
    <th mat-header-cell *matHeaderCellDef mat-sort-header> CLI </th>
    <td mat-cell *matCellDef="let row" style="width: 15%"> {{row.call_cli}} </td>
  </ng-container>

  <ng-container matColumnDef="call_service_name">
    <th mat-header-cell *matHeaderCellDef mat-sort-header> Campaign </th>
    <td mat-cell *matCellDef="let row" style="width:20px;"> {{row.call_service_name}} </td>
  </ng-container>
  
  <ng-container matColumnDef="call_type">
    <th mat-header-cell *matHeaderCellDef mat-sort-header style="max-width:20px !important"> CallType </th>
    <td mat-cell *matCellDef="let row"> {{row.call_type}} </td>
  </ng-container>
  <ng-container matColumnDef="Play">
    <th mat-header-cell *matHeaderCellDef> Play</th>
    <td mat-cell *matCellDef="let row">

      <button *ngIf="row.filepath" (click)="openDialog(row.filepath)" mat-stroked-button style="min-width:1%;" color="primary"><img src="../../assets/Images/play.png" /> </button>

      <button *ngIf="!row.filepath" mat-raised-button disabled style="min-width:1%;" color="primary"><img src="../../assets/Images/unavailable.png" /></button>
    </td>

  </ng-container>

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

<mat-paginator [pageSizeOptions]="[5,10, 25]"></mat-paginator>

I made sure that the matColumDef and the binding name are same for sorting to work properly.

1

Make sure you added

import { MatPaginatorModule, MatSortModule } from '@angular/material';

and

@NgModule({ exports: [ MatPaginatorModule, MatSortModule] })

in your corresponding module

Sowmea shree
  • 89
  • 2
  • 11
  • What do you mean by corresponding module? and its already imported in my app.module.ts file. – Prudhvi Bharadwaj M Mar 30 '19 at 11:42
  • Is there any reason are you creating new MatTableDataSource `this.dataSource = new MatTableDataSource( this.Result);` ? Try using `this.dataSource=this.Result` instead. I assume the dataSource you are pointing to paginator and sort is not same as the one you are setting in `this.dataSource = new MatTableDataSource( this.Result);` – Sowmea shree Mar 30 '19 at 12:00
  • initially i tried with the syntax as you pointed out, but it didn't work . So I used the syntax given by the angular-material. But it still didn't answer the question though. – Prudhvi Bharadwaj M Mar 30 '19 at 12:59
  • Is the response getting populated in `this.Result = this.Model.log` ? – Sowmea shree Mar 30 '19 at 13:37
  • 1
    yes. I'm able to get the data and i'm successfully able ti bind the data to the grid. The only problem is with pagination and sorting – Prudhvi Bharadwaj M Mar 30 '19 at 14:18
0

Within the method ngOnInit, it seems you're using dataSource member that has not yet been initialized.

You can get rid of method ngOnInit and move its content down to where the webservice result is handled.

this.webService.CallDetails(deatails)
  .subscribe(
     response => {
        this.Model = response;
        this.Result = this.Model.log
        this.dataSource = new MatTableDataSource( this.Result);
        this.dataSource.paginator = this.paginator;
        this.dataSource.sort = this.sort;        
     },
     error => console.error(error)
  ); 
uminder
  • 23,831
  • 5
  • 37
  • 72
0

Refer to angular Material Documentation on Tables here:

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

Note that - this.paginator and this.sort are called - AfterViewInit If you call these under onInit - this will not work.

hence, instead - call as below:

export class CategoriesListComponent implements OnInit, AfterViewInit {

  // VARIABLES
  dataSource = new MatTableDataSource<Category>([]);
  displayedColumns: string[] = ['id', 'name', 'icon', 'color', 'image'];

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

  constructor(
    private categoriesService: CategoriesService
  ) { }

  ngOnInit(): void {
    this._getDataTableCategoriesData();
  }

  ngAfterViewInit(): void {
      this._setTableAttributes();
  }

  private _getDataTableCategoriesData() {
    this.categoriesService.getCategories().subscribe(
      (categories) => {
        this.dataSource.data = categories;
      });
  }

  private _setTableAttributes() {
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
  }

  applyFilter(event: Event) {
    const filterValue = (event.target as HTMLInputElement).value;
    this.dataSource.filter = filterValue.trim().toLowerCase();

    if (this.dataSource.paginator) {
      this.dataSource.paginator.firstPage();
    }
  }
ajhavery
  • 264
  • 7
  • 16