0
votes

I am trying to create a mat-option with a nested mat-option structure base on a JSON object. I've tried to create a *ngFor together with a pipe to run through the structure of the JSON. So when selecting option "Actor" I'd like it to create another options fields for the elements in Actor and so on. However it only creates the "Actor"-option and then the error: "Cannot read property 'elements' of undefined" appears. So somehow running through the JSON-Structure during *ngFor doesn't work the way I want it to. What am I missing?

My HTML

<div *ngFor="let choice of choices; let i = index">
  <mat-form-field [ngStyle]="{'margin-left.px': 15*i}">
                  [value] = "selections?selections[i]:undefined">
  <mat-option *ngFor="let child of choice.elements | keys"
   {{child.name}}
</mat-option>
</mat-select>
</mat-form-field>
</div>

My ts + JSON + pipe:

  selections: string[] = [];
  this.incidentTree = 
[{"_id": {"$oid": "5e9aa4041c9d44000054070f"}, 
"Source": 
    [{"name": "Actor", 
      "id": 0, 
      "elements": [
                  {"name": "Individual",
                   "id": 0, 
                   "elements": [
                                {"name": "Outsider", 
                                 "id": 0},
                                {"name": "Insider",
                                 "id": 1}, 
                                {"name": "Trusted Insider", 
                                 "id": 2},
                                {"name": "Pirvileged Insider", "id": 3}]}, 
                 {"name": "Group", 
                  "id": 1, 
                  "elements": [
                                {"name": "Ad hoc", 
                                 "id": 0}, 
                                 {"name":"Established",
                                  "id": 1}]}, 
                 {"name": "Organzation", 
                  "id": 2,
                  "elements": [
                               {"name": "Competitor",
                                "id": 0}, 
                                {"name":"Supplier", 
                                 "id": 1},
                                {"name": "Partner",
                                 "id": 2},
                                {"name": "Customer",
                                "id": 3}]},
                               {"name": "Nation State", 
                                "id":3}]}]}]}]

  constructor() { }

  ngOnInit() {
    this.choices[0] = this.incidentTree
  }



My pipe keys:



import { Pipe, PipeTransform } from '@angular/core';
import { Source } from '../_classes/source';

@Pipe({
  name: 'keys'
})
export class KeysPipe implements PipeTransform {
  transform(value: any): any[] {
    if(value) {
      let dataArr = []
      let keyArr: any[] = Object.keys(value)

      // loop through the object,
      // pushing values to the return array
      keyArr.forEach((key: any) => {
          console.log(key)
          console.log(value[key])
          dataArr.push(value[key]);
      });

      console.log(dataArr)

      // return the resulting array
      return dataArr;
  }

}

}

1
please provide stackblitz reproduction. - Furqan S. Mahmoud

1 Answers

0
votes

What i can see from the HTML you provided is that you are missing the mat-select opening tag after the mat-form-field. Also key pipe is not required.

and most important:

this.choices = this.incidentTree.Source;