user3075338
user3075338

Reputation: 93

ERROR TypeError: Cannot read property X of undefined

I have following Interface to be used as a type for a JSON file :

export interface IIndustrySectors {
  IndustrySector: string;
  isSelected: string;
  dataSubjectCategories:string[];
  dataTypeCategories:string[];
  SubIndustries:[{
    IndustrySector: string;
    isSelected: string;
    dataSubjectCategories:string[];
    dataTypeCategories:string[];
    SubIndustries:[{}]
  }]
}

and, two services:

 
 
 // Read all the Data from the JSON file
 getMainIndustrySectors(): Observable<IIndustrySectors[]> {
    return this.http.get<IIndustrySectors[]>(this.industrySectorsURL).pipe(
      tap(((data) => console.log('All: ' + data) )),
      catchError(this.handleError)
    );
  }

//Get Specific object 
  getBySector(sector): Observable<IIndustrySectors|  undefined> {
    return this.getMainIndustrySectors().pipe(
      map((products: IIndustrySectors[]) => products.find(p => p.IndustrySector === sector)));

  }

Here is a part of the JSON file

 [
   {
      "IndustrySector":"Accommodation and Food Service Activities",
      "isSelected": "false",
      "dataSubjectCategories":["DS.Employees","DS.Collaborators"],
      "dataTypeCategories":"Personal Data",
      "SubIndustries": [
        {
          "IndustrySector":"Food and Beverage Service Activities",
          "isSelected": "false",
          "dataSubjectCategories":[],
          "dataTypeCategories":[],
          "SubIndustries":[]
        },
        {
          "IndustrySector":"Accommodation",
          "isSelected": "false",
          "dataSubjectCategories":["DS.Minor","DS.Parent","DS.Legal Person","DS.Natural Person","DS.Disable"],
          "dataTypeCategories":[],
          "SubIndustries":[]
        }
      ]
    }
  ]

The problem is when I call the service "getBySector" by following code:

this.readjsonService.getBySector(sector).subscribe(response=>{

      if(response.dataSubjectCategories.length>0)
      {
        for(i=0; i<response.dataSubjectCategories.length;i++ ){
          this.DSofSectores.push(response.dataSubjectCategories[i])
        }
      }
      
      })
when I see the the typeof the response, it is object!

It tthrows an error:

TypeError: Cannot read property 'dataSubjectCategories' of undefined "

it prints the values, though.

Why is it?

what do is that based on the sector, I get in "response" other data related to it and fill an array of type string which are bind to dropdown list. It works fine, but the following image showes what happens after selecting the sub sector:enter image description here

PLEASE help me , I am newbie and I am so sick of this :(( Thanks.

EDIT: when I say

 if (response == undefined) {
          throw new Error("sector not found");
        }
        else { .....

it passes the condition, meaning it is not undefined, yet it say "cannot read undefined"

Upvotes: 0

Views: 1780

Answers (3)

Roh&#236;t J&#237;ndal
Roh&#236;t J&#237;ndal

Reputation: 27202

TypeError: Cannot read property 'dataSubjectCategories' of undefined "

As above statement suggest that you are trying to access dataSubjectCategories of undefined object. Hence, response is not an object.

Use response[0].dataSubjectCategories instead of response.dataSubjectCategories

Demo

var response = [
   {
      "IndustrySector":"Accommodation and Food Service Activities",
      "isSelected": "false",
      "dataSubjectCategories":["DS.Employees","DS.Collaborators"],
      "dataTypeCategories":"Personal Data",
      "SubIndustries": [
        {
          "IndustrySector":"Food and Beverage Service Activities",
          "isSelected": "false",
          "dataSubjectCategories":[],
          "dataTypeCategories":[],
          "SubIndustries":[]
        },
        {
          "IndustrySector":"Accommodation",
          "isSelected": "false",
          "dataSubjectCategories":["DS.Minor","DS.Parent","DS.Legal Person","DS.Natural Person","DS.Disable"],
          "dataTypeCategories":[],
          "SubIndustries":[]
        }
      ]
    }
  ];
  
 var DSofSectores = [];
if(response[0].dataSubjectCategories.length>0) {
  for(i=0; i<response[0].dataSubjectCategories.length;i++ ) {
    DSofSectores.push(response[0].dataSubjectCategories[i])
  }
}

console.log(DSofSectores);

Upvotes: 0

kevin.groat
kevin.groat

Reputation: 1294

In your getBySector service, you say:

products.find(p => p.IndustrySector === sector))

Using Array#find will return undefined if no objects in the array match the selector, in this case if no products have IndustrySector === sector. This is why the service is required to have a return type of Observable<IIndustrySectors|undefined>.

If you're seeing this error at compile-time, or as an error in your IDE, it's because of this return type; it knows that the response can be undefined and therefore, you have to account for that possibility. Changing your consuming code to the following should fix the problem:

this.readjsonService.getBySector(sector).subscribe(response => {
  if (response !== undefined) {
    if(response.dataSubjectCategories.length > 0) {
      for(let i = 0; i < response.dataSubjectCategories.length; i++) {
        this.DSofSectores.push(response.dataSubjectCategories[i])
      }
    }
  }
})

But be aware that this means that, at runtime, when a sector is passed in that doesn't match any products, the for loop will not be executed.

Upvotes: 1

Reactgular
Reactgular

Reputation: 54771

The filter method does not find a match. So the observable is yielding a undefined.

getBySector(sector): Observable<IIndustrySectors|  undefined> {
     return this.getMainIndustrySectors().pipe(
        map((products: IIndustrySectors[]) => products.find(p => p.IndustrySector === sector)));
                                                     // ^^^ matches none
 }

Upvotes: 1

Related Questions