Sebastian R.
Sebastian R.

Reputation: 446

mdSort is undefined in Angular Material 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']);
      }
    });
  }
}

Upvotes: 2

Views: 3531

Answers (4)

The Aelfinn
The Aelfinn

Reputation: 17038

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{}

Upvotes: 2

Stephen Paul
Stephen Paul

Reputation: 39025

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

Upvotes: 2

Sebastian R.
Sebastian R.

Reputation: 446

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

Upvotes: 4

Habeeb
Habeeb

Reputation: 1040

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);
}

Upvotes: 1

Related Questions