Reputation: 4198
I am new to Angular 6 so please forgive if this is a silly question.
I have an outer component and some inner components such that the outer one passes info to the inner one.
In this case, I am passing 2 values, a JSON (which works fine) and a filter string [filterString]
(which is the problem).
When the value of the allSegmentsFilter
model in the outer one changes, I get the below error:
TypeError: Cannot read property 'currentValue' of undefined
at :
<app-json-to-table-viewer [rawJSON]="x" [filterString]="allSegmentsFilter"></app-json-to-table-viewer>
Outer component view (abstracted for brevity):
<div class="col-lg-8">
<div class="row">
<mat-form-field>
<input matInput
placeholder="Search all segments"
[(ngModel)]="allSegmentsFilter" >
</mat-form-field>
</div>
<div class="row" *ngFor="let x of payfilemessage;" >
<div >
<app-json-to-table-viewer [rawJSON]="x" [filterString]="allSegmentsFilter"></app-json-to-table-viewer>
</div>
<br>
</div>
</div>
Outer Component's code
export class OuterComponent implements OnInit {
payfilemessage = [/**abstracted, assume this has some values */];
allSegmentsFilter="";
constructor() { }
applyPayFileMessageFilter(filterValue: string) {
console.log("TBD filter:"+filterValue);
}
ngOnInit() {
}
}
Inner Component View:
<mat-tab-group class="mat-elevation-z2">
<mat-tab label="Keys as columns">
<div>
<mat-form-field>
<input matInput
(keyup)="applyFilter($event.target.value)"
placeholder="Filter"
[(ngModel)]="filterString"
>
</mat-form-field>
<table mat-table [dataSource]="KeysAsCols.Source" matSort>
<ng-container *ngFor="let key of KeysAsCols.Columns;" [matColumnDef]="key">
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{key}} </th>
<td mat-cell *matCellDef="let element"> {{element[key]}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="KeysAsCols.Columns"></tr>
<tr mat-row *matRowDef="let row; columns: KeysAsCols.Columns;"></tr>
</table>
<mat-paginator [pageSizeOptions]="[5, 10, 20]" showFirstLastButtons></mat-paginator>
</div>
</mat-tab>
<mat-tab label="Keys as rows"> Keys as rows </mat-tab>
<mat-tab label="Raw JSON "> Raw JSON </mat-tab>
</mat-tab-group>
Inner Component Code:
import { Component, OnInit, Input, SimpleChanges, ViewChild } from '@angular/core';
import { MatPaginator, MatSort, MatTableDataSource } from '@angular/material';
@Component({
selector: 'app-json-to-table-viewer',
templateUrl: './json-to-table-viewer.component.html',
styleUrls: ['./json-to-table-viewer.component.scss']
})
export class JsonToTableViewerComponent implements OnInit {
@Input() rawJSON: any[];
@Input() filterString:string="";
@ViewChild(MatPaginator) paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
KeysAsCols = {
Source: <MatTableDataSource<any>> null,
Columns: <String[]> []
};
constructor() { }
ngOnChanges(changes: SimpleChanges) {
if (this.rawJSON) {
if (changes.rawJSON.currentValue != changes.rawJSON.previousValue )
{
console.log('value changed!')
this.KeysAsCols.Source = new MatTableDataSource<any>(this.rawJSON);
this.setAllKeys();
this.KeysAsCols.Source.paginator=this.paginator;
this.KeysAsCols.Source.sort=this.sort;
}
}
}
setAllKeys(){
this.KeysAsCols.Columns = this.rawJSON.length==0?[]:Object.keys(this.rawJSON[0]);
}
applyFilter(filterValue: string) {
this.KeysAsCols.Source.filter = filterValue.trim().toLowerCase();
}
ngOnInit() {
}
ngAfterViewInit() {
}
}
I have tried providing default values to model in both components, but it still throws an error.
Upvotes: 2
Views: 7678
Reputation: 499
you can just add defensive condition in your onchanges function like:
if (this.rawJSON && changes.rawJSON) {
if (changes.rawJSON.currentValue != changes.rawJSON.previousValue )
{
console.log('value changed!')
this.KeysAsCols.Source = new MatTableDataSource<any>(this.rawJSON);
this.setAllKeys();
this.KeysAsCols.Source.paginator=this.paginator;
this.KeysAsCols.Source.sort=this.sort;
}
}
Upvotes: 2