Search code examples
jsonangularnestedrxjsangular-ngmodel

Angular dependent select boxes doesn't work


The first box works well. But the second one doesn't work. They depend on each other. And the error does not appear.

I can't try anything else because it doesn't any errors.

city.service.ts

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class CityService {

  constructor(private http:Http) { }
      getCitys(){
    return this.http.get("http://localhost:3003/api")
      .map(response => response.json());
  }
}

city.ts

export interface City 
  { 
   name: string,
   value:number,
   down: Down[]
  }
export interface Down
         {
   name: string,
   value:number,
   places: Places[]
}

  export interface Places    
          {
   name: string;
   pname:string;
   unvan: string
  }

city.component.ts

@Component({
  selector: 'app-city',
  templateUrl: './city.component.html',
  styleUrls: ['./city.component.css']
})
export class CityComponent implements OnInit {
  cityDatas: [];
downDatas: [];
placesDatas: [];

  constructor(private cityService: CityService) { }

  ngOnInit() {
           this.cityService.getCitys().subscribe(d => { 
        this.cityDatas = d;
        this.downDatas = d.down;
        this.placesDatas = d.places });

  }


}

city.component.html

  <select [(ngModel)]="selectedData">
    <option [ngValue]="null" selected disabled>First</option>
      <option *ngFor="let data of cityDatas" [value]="data">
        {{ data.name }}
      </option>
    </select>

            <select [(ngModel)]="selectedDw" >
      <option [ngValue]="null"  selected disabled>Second</option>
        <option *ngFor="let dw of downDatas" [value]="dw">
          {{dw.name}}
        </option>
    </select>

And api json

[
      {"name":"City1",
      "value":1,
      "down":
        [{"name":"Down11",
        "value":101,
        "places":
          [{"name":"Place111",
            "pname":"JustPlace",
            "unvan":"center"
          },
        {"name":"Place112",
            "pname":"Jp",
            "unvan":"center"
          }]
        },
{"name":"Down12",
        "value":102,
        "places":
          [{"name":"Place121",
            "pname":"Jp",
            "unvan":"side"
          },
        {"name":"Place122",
            "pname":"Jp",
            "unvan":"side"
          }]
        }
      ]
      },
            {"name":"City2",
      "value":2,
      "down":
        [{"name":"Down21",
        "value":103,
        "places":
          [{"name":"Place211",
            "pname":"Jp",
            "unvan":"center"
          },
        {"name":"Place212",
            "pname":"Jp",
            "unvan":"center"
          }]
        },
{"name":"Down22",
        "value":104,
        "places":
          [{"name":"Place221",
            "pname":"JustPlace",
            "unvan":"side"
          },
        {"name":"Place222",
            "pname":"Jp",
            "unvan":"side"
          }]
        }
      ]
      }
     ]

When I choose the first one, I want the second to work. And I want the results displayed. But I couldn't run the second select box and the console didn't give any errors. Why does not work? And how will it work?


Solution

  • downDatas is undefined, because d in the subscription is an array, not an object. Try to implement it in this way (after selecting selectedData in the first select, this data will be available in the second):

    <select [(ngModel)]="selectedData">
      <option selected disabled>First</option>
      <option *ngFor="let data of cityDatas; index as i;" [value]="i">
        {{ data.name }}
      </option>
    </select>
    
    <select [(ngModel)]="selectedDw" >
      <option [ngValue]="null"  selected disabled>Second</option>
      <option *ngFor="let dw of cityDatas[selectedData]?.down" [value]="dw">
        {{ dw.name }}
      </option>
    </select>
    

    stackblitz