0

I'm working on an upgrade from Angular 8 to 12 and got some errors. Most of them are fixed. The only one left is this one The error

This error means that the sortChange is undefined. The data is displayed in the table. I use this code for the sort function:

ngOnInit(): void {       
this.currentPageIndex = 0;
this.currentPageSize = this.paginationSettings.defaultPageSize;

this.setDataSource(this.entities);

this.sort.sortChange.subscribe((sort: Sort) => {
  debugger;
  return this.sortChanged(sort);
});
}

When the view is loaded I set the event this.sort

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

The value if variables are

  @ViewChild(MatTable, { static: true }) table: MatTable<any>;
  @ViewChild(MatPaginator) paginator: MatPaginator;
  @ContentChild(MatSort, { static: true }) sort: MatSort;
  @ContentChildren(MatHeaderRowDef) headerRowDefs!: QueryList<MatHeaderRowDef>;
  @ContentChildren(MatRowDef) rowDefs!: QueryList<MatRowDef<TEntity>>
  @ContentChildren(MatColumnDef, { descendants: true }) columnDefs!: QueryList<MatColumnDef>;
  @Input() entities: TEntity[]; (the data source)

The HTML:

<!-- user component -->
<lq-list
    matSort
    (settingsChanged)="listSettingsChanged.emit($event)"
    [entities]="users"
    [isLoading]="isLoading"
    [displayedColumns]="displayedColumns"
    [paginationSettings]="paginationSettings"
    [totalEntityCount]="totalUserCount"
    >
    <ng-container matColumnDef="email">
        <mat-header-cell *matHeaderCellDef mat-sort-header> Email </mat-header-cell>
        <mat-cell *matCellDef="let element"> {{element.email}} </mat-cell>
      </ng-container>

    <ng-container matColumnDef="firstName">
        <mat-header-cell *matHeaderCellDef mat-sort-header> Voornaam </mat-header-cell>
        <mat-cell *matCellDef="let element"> {{element.firstName}} </mat-cell>
    </ng-container>

    <ng-container matColumnDef="lastName">
        <mat-header-cell *matHeaderCellDef mat-sort-header> Achternaam </mat-header-cell>
        <mat-cell *matCellDef="let element"> {{element.lastName}} </mat-cell>
    </ng-container>
    <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
    <mat-row *matRowDef="let row; columns: displayedColumns;" [routerLink]="['/users/', row.id]" class="pointer"></mat-row>
</lq-list>

<!-- the container-->
<mat-table [dataSource]="dataSource">
  <ng-content></ng-content>
</mat-table>
<lq-paginator
    (page)="paginationSettingsChanged($event)"
    [totalEntityCount]="totalEntityCount"
    [paginationSettings]="paginationSettings"
></lq-paginator>

The ts table component

import { Component, Input, EventEmitter, Output, ViewChild, OnInit, AfterViewInit, SimpleChanges, OnChanges } from '@angular/core';
import { User } from '@app/users/models/user';
import { PaginationSettings } from '@app/core/constants/list-pagination-settings';
import { ListSettingsChangedEvent } from '@app/core/models/list-settings-changed-event';

@Component({
  selector: 'lq-user-list',
  templateUrl: './user-list.component.html',
  styleUrls: ['./user-list.component.scss'],
})
export class UsersListComponent {
  /**
   * The user entities to display
   * @type {User[]}
   * @memberof UsersListComponent
   */
  @Input() users: User[];

  /**
   * Indicator whether the list is loading
   * @type {boolean}
   * @memberof UsersListComponent
   */
  @Input() isLoading: boolean;

  /**
   * Pagination settings
   * @type {PaginationSettings}
   * @memberof UsersListComponent
   */
  @Input() paginationSettings: PaginationSettings;

  /**
   * The total user count
   * @type {number}
   * @memberof UsersListComponent
   */
  @Input() totalUserCount: number;

  /**
   * The event emitter for when the list settings have changed
   * @type {EventEmitter<ListSettingsChangedEvent>}
   * @memberof UsersListComponent
   */
  @Output() listSettingsChanged: EventEmitter<ListSettingsChangedEvent> = new EventEmitter<ListSettingsChangedEvent>();

  /**
   * The columns to display
   * @type {string[]}
   * @memberof UsersListComponent
   */
  displayedColumns: string[] = ['email', 'firstName', 'lastName'];
}
jub0bs
  • 60,866
  • 25
  • 183
  • 186
ido435
  • 27
  • 2
  • 5
  • it seems that you miss the `sortChanged` implementation or you're mispelling it. where it should be located. [MatSort](https://material.angular.io/components/sort/api) does not provide it in the api, so I guess you forgot about something – akkonrad Jul 16 '21 at 08:13

1 Answers1

0

@ContentChild(MatSort, { static: true }) sort: MatSort; will be set after the content has been initialized.

So this.sort is undefined in ngOnInit(). Move it to ngAfterContentInit().

Also matSort directive needs to be a part of the projected content.

<lq-list
    (settingsChanged)="listSettingsChanged.emit($event)"
    [entities]="users"
    [isLoading]="isLoading"
    [displayedColumns]="displayedColumns"
    [paginationSettings]="paginationSettings"
    [totalEntityCount]="totalUserCount"
    >
    <ng-container matSort>
        <ng-container matColumnDef="email">
            <mat-header-cell *matHeaderCellDef mat-sort-header> Email </mat-header-cell>
            <mat-cell *matCellDef="let element"> {{element.email}} </mat-cell>
          </ng-container>
    ...
    </ng-container>
</lq-list>

John Malkoln
  • 451
  • 4
  • 10
  • Thanks for your response! I added the this.sort to the ngAfterContentInit() but it seems not to work. The value is still undefined. – ido435 Jul 16 '21 at 08:33
  • @ido435 answer is improved, I found that you're using `matSort` outside of the projected content. So `@ContentChild` is not able to query it. – John Malkoln Jul 16 '21 at 10:08