Angular5 - TypeError: Cannot read property 'template' of undefined

51,919

Solution 1

I forgot to define the header cell for the actions. So it was throwing that error. Here is the code which solved this problem.

<ng-container matColumnDef="actions">
  <mat-header-cell *matHeaderCellDef></mat-header-cell>
  <mat-cell *matCellDef="let row">
    <button mat-button (click)="showDetails(row)">DETAILS</button>
    <button mat-button (click)="editItem(row)">EDIT</button>
    <button mat-button (click)="deleteItem(row)">DELETE</button>
  </mat-cell>
</ng-container>

Solution 2

I faced this error because, I forget to add th and td in ng-container

<ng-container matColumnDef="actions">

</ng-container>

Solution 3

Check the configuration in .ts file

displayedColumns = ['name', 'description', 'action'];
dataSource = new MatTableDataSource<Element>(ELEMENT_DATA);

const ELEMENT_DATA: Element[] = [
    { name: '', description: '' },
    { name: '', description: '' }
]

Solution 4

I had this same issue. I had accidentally used *matCelLDef instead of *matCellDef.

Solution 5

My solution was to add the mat-cell element inside of the ng-container element:

The original code was:

  <ng-container matColumnDef="testColumn">
    <mat-header-cell *matHeaderCellDef>testColumn</mat-header-cell>
  </ng-container>

The code update that fixed it:

  <ng-container matColumnDef="testColumn">
    <mat-header-cell *matHeaderCellDef>testColumn</mat-header-cell>
    <mat-cell *matCellDef="let element">{{ element.testColumn}}</mat-cell>
  </ng-container>
Share:
51,919
Raghu M U
Author by

Raghu M U

Updated on July 26, 2021

Comments

  • Raghu M U
    Raghu M U almost 3 years

    I have added EDIT, DELETE and DETAILS buttons to each row in mat-table using Angular [email protected]. All buttons are working but, * I am getting an error "Cannot read property 'template' of undefined" and * for each button click, everything is displaying on the same page

    itemlist.component.html

    <mat-table #table [dataSource]="dataSource">
      <ng-container matColumnDef="name">
        <mat-header-cell *matHeaderCellDef> Name </mat-header-cell>
        <mat-cell *matCellDef="let row"> {{row.name}} </mat-cell>
      </ng-container>
    
      <ng-container matColumnDef="description">
        <mat-header-cell *matHeaderCellDef> Description </mat-header-cell>
        <mat-cell *matCellDef="let row"> {{row.description}} </mat-cell>
      </ng-container>
    
      <ng-container matColumnDef="actions">
        <mat-cell *matCellDef="let row">
          <button mat-button (click)="showDetails(row)">DETAILS</button>
          <button mat-button (click)="editItem(row)">EDIT</button>
          <button mat-button (click)="deleteItem(row)">DELETE</button>
        </mat-cell>
      </ng-container>
    
      <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
      <mat-row *matRowDef="let row; columns:displayedColumns"></mat-row>
    </mat-table>
    

    itemlist.component.ts

    export class ItemListComponent {
      @Input() dataSource;
      displayedColumns = ['name', 'description', 'actions'];
    
      @Input() items: Item[];
      @Output() onEdit = new EventEmitter<Item>();
      @Output() onShow = new EventEmitter<Item>();
      @Output() onDelete = new EventEmitter<Item>();
    
      itemsTrackByFn = (index: string, item: Item) => item.id;
    
      showDetails(item: Item) {
        this.onShow.emit(item);
      }
      editItem(item: Item) {
        this.onEdit.emit(item)
      }
      deleteItem(item: Item) {
        this.onDelete.emit(item)
      }
    }
    

    itemindex.component.html

    <app-item-list [dataSource]="dataSource"
                  (onShow)="showItem($event)"
                  (onDelete)="deleteItem($event)"
                  (onEdit)="editItem($event)"
    ></app-item-list>
    

    itemindex.component.ts

    export class ItemIndexComponent implements OnInit {
      items$: Observable<Item[]>;
      public dataSource: ItemsDatasource;
    
      constructor(public store: Store<fromRoot.State>, private router: Router){}
    
      ngOnInit() {
        this.items$ = this.store.select(fromItems.getAllItems);
        this.store.dispatch(new itemsActions.LoadAll());
        this.dataSource = new ItemsDatasource(this.items$);
      }
    
      editItem(item: Item) {
        this.store.dispatch(new itemsActions.SetCurrentItemId(item.id));
        this.router.navigate(['/items', item.id, 'edit'])
      }
      showItem(item: Item) {
        this.store.dispatch(new itemsActions.SetCurrentItemId(item.id));
        this.router.navigate(['/items', item.id])
      }
      deleteItem(item: Item) {
         this.store.dispatch(new itemsActions.Delete(item.id));
       }
     }
    }
    
    
    export class ItemsDatasource extends DataSource<Item> {
    
      public constructor(private items$: Observable<Item[]>) {
        super()
      }
    
      public connect(collectionViewer: CollectionViewer): Observable<Item[]> {
        return this.items$;
      }
    
      public disconnect(collectionViewer: CollectionViewer): void {}
    }
    

    Any suggestion would be helpful