2

I am working with Angular Material Table. I want to sort the items with mdSort, but when i start the App the table says that the view child of mdsort is undefined. What is the misatke?

My code is the same as in the example here: material.angular.io

here is the error log:

ERROR TypeError: Cannot read property 'mdSortChange' of undefined
at AliasDataSource.webpackJsonp.../../../../../src/app/admin/admin.component.ts.AliasDataSource.connect (admin.component.ts:106)
at MdTable.webpackJsonp.../../../cdk/@angular/cdk.es5.js.CdkTable._observeRenderChanges (cdk.es5.js:2005)
at MdTable.webpackJsonp.../../../cdk/@angular/cdk.es5.js.CdkTable.ngDoCheck (cdk.es5.js:1970)
at checkAndUpdateDirectiveInline (core.es5.js:10897)
at checkAndUpdateNodeInline (core.es5.js:12382)
at checkAndUpdateNode (core.es5.js:12321)
at debugCheckAndUpdateNode (core.es5.js:13182)
at debugCheckDirectivesFn (core.es5.js:13123)
at Object.eval [as updateDirectives] (AdminComponent.html:27)
at Object.debugUpdateDirectives [as updateDirectives] (core.es5.js:13108)

my HTML table snipped

 <md-table #table [dataSource]="aliasSource" mdSort>

    <ng-container cdkColumnDef="aliasId" md-sort-header>
      <md-header-cell *cdkHeaderCellDef> Alias</md-header-cell>
      <md-cell *cdkCellDef="let a"> {{ a.AliasName }}</md-cell>
    </ng-container>
    ...
 </md-table>

the class where he say it's undefined

export class AliasDataSource extends DataSource<any> {
constructor(private _aliasDatabase: AliasDatabase, private _sort: MdSort) {
  super();
}

/** Connect function called by the table to retrieve one stream containing 
the data to render. */
 connect(): Observable<Mailalias[]> {
const displayDataChanges = [
  this._aliasDatabase.dataChange,
  this._sort.mdSortChange, // here is the point where the exception throws
];

return Observable.merge(...displayDataChanges).map(() => {
  return this.getSortedData();
});
}

disconnect() {}

/** Returns a sorted copy of the database data. */
getSortedData(): Mailalias[] {
const data = this._aliasDatabase.data.slice();
if (!this._sort.active || this._sort.direction == '') { return data; }

return data.sort((a, b) => {
  let propertyA: number|string = '';
  let propertyB: number|string = '';

  switch (this._sort.active) {
    case 'aliasId': [propertyA, propertyB] = [a.ID, b.ID]; break;
    case 'adresse': [propertyA, propertyB] = [a.FromAddr, b.FromAddr]; break;
    case 'name': [propertyA, propertyB] = [a.FromName, b.FromName]; break;
  }

  let valueA = isNaN(+propertyA) ? propertyA : +propertyA;
  let valueB = isNaN(+propertyB) ? propertyB : +propertyB;

  return (valueA < valueB ? -1 : 1) * (this._sort.direction == 'asc' ? 1 : 
 -1);
});
}
}

my main class of the TS File

export class AdminComponent implements OnInit {



aliasColumns = ['aliasId', 'adresse', 'name', 'host', 'password', 'port', 'ssl', 'user', 'menu'];
  aliasSource: AliasDataSource | null;
  @ViewChild(MdSort) sort: MdSort;
  alias: Mailalias[];
  isLoading = false;

  constructor(private ms: MailService, private router: Router) {
  }

  ngOnInit() {
    this.isLoading = true;
    console.log(this.sort);
    this.ms.getAll().subscribe(res => {
      this.alias = res;
      const aliasDatabase = new AliasDatabase(res);
      this.aliasSource = new AliasDataSource(aliasDatabase, this.sort);
      // this.aliasSource = new AliasDataSource(aliasDatabase);
      this.isLoading = false;
      this.isLoading = false;
      const a = AliasFactory.errorObject(res);
      if (a.Status === 401) {
        this.router.navigate(['/login']);
      }
    });
  }
}
6
  • Post full error. Console log or build error? Commented Jul 10, 2017 at 8:45
  • "after " connect(): Observable<Mailalias[]> { "add" console.log(this._sort) Commented Jul 10, 2017 at 9:21
  • Also check that your are passing sort @ViewChild(MdSort) sort: MdSort; ngOnInit() { this.dataSource = new ExampleDataSource(this.exampleDatabase, this.sort); } Commented Jul 10, 2017 at 9:22
  • It's passed in the ngOnit but there it is also undefined and he say in the log undefined, too. Commented Jul 10, 2017 at 9:26
  • Check the case again @ViewChild(MdSort) sort: MdSort; Commented Jul 10, 2017 at 9:30

4 Answers 4

4

So now i found my mistake id had in my div container a ngIf that hide's my table -.-

When someone have the same problem look if you have a ngIf in a tag before !!!

But thanks for the help @Habeeb

Sign up to request clarification or add additional context in comments.

Comments

2

I also encountered this. don't forget to add MdSortModule to you list of imports.

Comments

2

Add MdSortModule to your module's list of imports.

If you are defining an NgModule, and a component of the module uses mdSort, you'll have to update the NgModule's imports as follows:

@NgModule({
    imports:[MdTableModule,
             ...
             MdSortModule
            ],
     ...
})
export class ModuleThatImportsMdSortModule{}

Comments

1

In HTML

 <table mdSort (mdSortChange)="sortData($event)">

In TS have the implementation and logic. Refer example

Initial value

desserts = [
    {name: 'Frozen yogurt', calories: '159', fat: '6', carbs: '24', protein: '4'},
    {name: 'Ice cream sandwich', calories: '237', fat: '9', carbs: '37', protein: '4'},
    {name: 'Eclair', calories: '262', fat: '16', carbs: '24', protein: '6'},
    {name: 'Cupcake', calories: '305', fat: '4', carbs: '67', protein: '4'},
    {name: 'Gingerbread', calories: '356', fat: '16', carbs: '49', protein: '4'},
  ];

const data = this.desserts.slice();

Sorting logic

this.sortedData = data.sort((a, b) => {
      let isAsc = sort.direction == 'asc';
      switch (sort.active) {
        case 'name': return compare(a.name, b.name, isAsc);
        case 'calories': return compare(+a.calories, +b.calories, isAsc);
        case 'fat': return compare(+a.fat, +b.fat, isAsc);
        case 'carbs': return compare(+a.carbs, +b.carbs, isAsc);
        case 'protein': return compare(+a.protein, +b.protein, isAsc);
        default: return 0;
      }
    });

implement the below function too

function compare(a, b, isAsc) {
  return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
}

4 Comments

this work but with md-table the example want work by me at the point @ViewChild(MdSort) sort: MdSort;
<md-table #table [dataSource]="dataSource" mdSort> Can you mdSort directive in you html?
I've update my post with a html snipped from my table. In the ts File he say the Viewchild of MdSort is undefined. But i defined it everywhere :(
i added also the class where he throws the exception

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.