11

In my Angular application, my @ViewChild instance is failing to fill HTL matSort.

mycomponent.ts:

import { MatSort } from '@angular/material';

export class MyClassComponent {
     @ViewChild(MatSort) sort: MatSort;

}

ngOnInit() {
    console.log(this.sort); // undefined
}

mycomponent.html:

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

</mat-table>

I need to use sortChange from matSort but it is always returned undefined.

HDJEMAI
  • 9,436
  • 46
  • 67
  • 93
Luiz Ricardo Cardoso
  • 1,554
  • 4
  • 16
  • 37

5 Answers5

14

It will be initialized and available in the AfterViewInit lifecycle hook:

export class MyClassComponent implements AfterViewInit {
  @ViewChild(MatSort) sort: MatSort;

  ngAfterViewInit() {
    console.log(this.sort); // MatSort{}
  }
}

More info on lifecycle hooks here: https://angular.io/guide/lifecycle-hooks.

vince
  • 7,808
  • 3
  • 34
  • 41
  • 1
    It is not entering the ngAfterViewInit () method, I implemented AfterViewInit and created the method as it is in the documentation, but it does not enter the method when the page loads. – Luiz Ricardo Cardoso Mar 16 '18 at 11:42
  • It was running `ngOnInit` but now it's not running `ngAfterViewInit`? Check for typos and such...that behavior seems odd. – vince Mar 16 '18 at 12:30
  • `ngOnInit` With this method this.sort comes undefined, but with `ngAfterViewInit` method... I can not know since neither is done the method call in execution... there are no typos – Luiz Ricardo Cardoso Mar 16 '18 at 14:04
  • After several attempts, this is calling the `ngAfterViewInit ()` method, but within this `this.sort` method remains `undefined`. – Luiz Ricardo Cardoso Mar 16 '18 at 15:14
  • Another problem is also that `mat-sort-header` has no effect on the table, only `@ViewChild matPaginator` is returned. – Luiz Ricardo Cardoso Mar 16 '18 at 15:28
  • I have the same issue. :-/ – mminnie May 29 '18 at 11:46
  • 5
    I had the same issue.....but mine was related to a *ngIf. See this answer [https://stackoverflow.com/a/48322035/2022096](https://stackoverflow.com/a/48322035/2022096) – mminnie May 29 '18 at 11:57
  • 3
    I _thought_ it was fixed. Ultimately it ended up being I needed to import the MatSortModule into the @NgModule. I was importing MatSortModule in my component but not into the NgModule. – mminnie May 29 '18 at 12:13
9

You have probably already imported at the class level with:

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

This makes the types MatSort and MatTableDataSource available within your .ts class. However, you are also trying to use the related modules as directives in your component's .html file, to do this your app.module.ts needs to be importing them, I do this with a separate NgModule that imports all of the material components I use i.e.

material\material.module.ts

import { NgModule } from '@angular/core';

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

@NgModule({
  imports: [
      MatTableModule,
      MatSortModule, 
    ],
  exports: [
      MatTableModule,
      MatSortModule, 
    ]
})
export class MaterialModule { }

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { HttpClientModule } from '@angular/common/http';

import { MaterialModule } from './material/material.module';
import { AppComponent } from './app.component';
import { myComponent } from './my/my.component';

@NgModule({
  declarations: [
    AppComponent,
    MyComponent
  ],
  imports: [
    BrowserModule,
    MaterialModule,
    BrowserAnimationsModule,
    HttpClientModule,
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
Stephen Turner
  • 7,125
  • 4
  • 51
  • 68
5

I'm working with angular 7 what solved the issue for me was adding MatSortModule in the app.modules.ts. The error I got is the one mentioned here. No indication appeared about the MatSortModule being missing.

Original answer here: Angular 5 - Missing MatSortModule

Community
  • 1
  • 1
Noy Oliel
  • 1,430
  • 3
  • 13
  • 26
4

In Angular 8 I had to use a setter and optional parameter static=false:

   @ViewChild(MatSort, {static: false})
   set sort(sort: MatSort) {
      this.sortiments.sort = sort;
      this.selectedSortiments.sort = sort;
   }

I found the answer from here: https://stackoverflow.com/a/47519683/3437868 https://github.com/angular/components/issues/15008#issuecomment-516386055

Tai Truong
  • 668
  • 1
  • 8
  • 11
  • 1
    In my case, setting the ViewChild parameter `{static: true}` ensures the property has a value when I access it in `ngOnChanges()`. Your answer pointed me in the right direction – NJS Oct 19 '21 at 18:54
2
  1. You must add @ViewChild(MatSort,{static:false}) sort: MatSort;
  2. Make sure that there no *ngIf directory in your table template
  • 2
    `{static: false}` is the default for `@ViewChild` though: https://angular.io/api/core/ViewChild – Dai Nov 19 '21 at 01:21