Sajjan Sarkar
Sajjan Sarkar

Reputation: 4198

Cannot read property 'currentValue' of undefined

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

Answers (1)

alokstar
alokstar

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

Related Questions