如何在Angular中从JSON内的列表提取城市值并正确渲染至下拉选择器
解决Angular下拉选择器中嵌套城市数组的展开问题
你遇到的核心问题是当前的*ngFor在遍历每个部门对象,然后直接输出该部门的整个城市数组,Angular会自动把数组转换成逗号分隔的字符串作为单个选项。要实现每个城市单独成为下拉选项,我们需要把嵌套的城市数组展开,同时先修复代码里的一个变量冲突bug:
第一步:修复变量名冲突
你的组件里存在变量名重复问题:public cities: City[] = []; 和构造函数里的 public cities: CitiesService; 重名了,这会导致服务实例被覆盖,后续调用服务方法大概率出错。先修改组件代码:
import { Component, OnInit } from '@angular/core'; import { CitiesService } from 'src/app/services/cities.service'; // 建议把接口名改成Department,更贴合数据结构的实际含义 interface Department { department: string; cities: string[]; } @Component({ selector: 'app-nueva-organizacion', templateUrl: './nueva-organizacion.component.html', styleUrls: ['./nueva-organizacion.component.css'], }) export class NuevaOrganizacionComponent implements OnInit { // 存储所有部门数据 public departments: Department[] = []; // 如果用方案二,这里新增存储所有城市的一维数组 // public allCities: string[] = []; constructor( // 把服务实例的变量名改成cityService,避免和数据变量冲突 private cityService: CitiesService, ) {} ngOnInit(): void { this.cityService .getJSON( 'https://raw.githubusercontent.com/marcovega/colombia-json/master/colombia.min.json' ) .subscribe((res: any) => { this.departments = res; // 如果用方案二,在这里添加合并城市的逻辑 // this.allCities = res.flatMap(dept => dept.cities); }); } }
方案一:模板中使用嵌套*ngFor(无需修改组件逻辑)
直接在模板里用<ng-container>遍历每个部门,再嵌套遍历该部门的城市数组,这样每个城市会生成单独的<option>标签:
<div class="form-input"> <select id="city" class="custom-select"> <option selected>Choose one...</option> <!-- 先遍历每个部门 --> <ng-container *ngFor="let dept of departments"> <!-- 再遍历当前部门下的所有城市 --> <option *ngFor="let city of dept.cities"> {{ city }} </option> </ng-container> </select> </div>
方案二:组件中预处理数据(适合需复用城市列表的场景)
如果后续业务中还需要单独使用所有城市的列表,可以在组件里把所有部门的城市合并成一个一维数组,然后模板直接遍历这个数组:
在组件的subscribe回调里添加合并逻辑:
this.cityService.getJSON(url).subscribe((res: any) => { this.departments = res; // 使用flatMap把嵌套的cities数组展开成一维数组 this.allCities = res.flatMap(dept => dept.cities); });
然后模板简化为:
<div class="form-input"> <select id="city" class="custom-select"> <option selected>Choose one...</option> <option *ngFor="let city of allCities"> {{ city }} </option> </select> </div>
两种方式都能实现你想要的下拉效果:如果只是单纯展示城市,方案一更直接;如果后续有复用城市列表的需求,方案二更灵活。
内容的提问来源于stack exchange,提问作者Kalaus
相关产品推荐
相关产品推荐

