Angular mat-select用户列表被最后请求的项目用户数据覆盖问题求助
问题根因
你当前的代码在获取所有项目列表后,循环给每个项目发起用户查询的异步请求,所有请求返回的结果都直接赋值给同一个customersUsuarios变量。由于异步请求的返回顺序不受代码执行顺序控制,最后返回的请求结果会覆盖之前所有请求的赋值,因此下拉框永远只展示最后返回的那个项目的用户数据。
解决方案
根据你实际的业务需求选择对应解法:
场景1:选中对应项目后,下拉框仅展示该项目的用户(绝大多数场景的需求)
你不需要在拿到项目列表时就批量请求所有项目的用户,改为监听选中项目的ID变化,单独请求当前选中项目的用户即可:
- 新增项目用户加载方法,同时监听项目ID变化
// 你的表单组变量,替换成你实际的表单变量名 declare yourFormGroup: FormGroup; // 加载指定项目的用户列表 loadProjectUsers(projectId: number) { this.API.getDataUsuariosNoRegistrados(projectId) .subscribe((userList: any) => { this.customersUsuarios = userList; // 切换项目后清空之前选中的用户,避免表单值不匹配 this.yourFormGroup.get('userId')?.reset(); }); } // 原有获取项目列表的逻辑 this.API.getProjects() .subscribe((data: CustomerProyecto[]) => { this.customersProyecto = data; // 如果有默认选中的项目,默认加载对应项目的用户 if (this.defaults?.id) { this.loadProjectUsers(this.defaults.id); } }); // 监听表单中项目ID的变化,自动加载对应用户 this.yourFormGroup.get('projectId')?.valueChanges.subscribe(projectId => { if (projectId) this.loadProjectUsers(projectId); })
如果你的页面有显性的项目选择下拉框,也可以给下拉框绑定(selectionChange)="loadProjectUsers($event.value)事件实现触发。
场景2:下拉框需要展示所有项目的所有用户,不要覆盖
修改请求成功后的赋值逻辑,将新返回的用户数组合并到原有数组中即可:
import { forkJoin, switchMap } from 'rxjs'; // 推荐用rxjs高阶操作符优化嵌套订阅,避免回调地狱和内存泄漏 this.API.getProjects() .pipe( switchMap(projects => { this.customersProyecto = projects; // 生成所有项目用户请求的Observable数组 const userRequests = projects.map(project => this.API.getDataUsuariosNoRegistrados(project.id)); // 批量等待所有请求返回 return forkJoin(userRequests); }) ) .subscribe(userLists => { // 合并所有项目的用户数组 this.customersUsuarios = userLists.flat(); // 如果需要用户去重可以加以下逻辑,按用户ID去重 // this.customersUsuarios = Array.from(new Map(this.customersUsuarios.map(u => [u.id, u])).values()); })
如果不想改rxjs写法,也可以直接修改原逻辑的赋值语句:
// 原逻辑中请求成功后的赋值改为合并,不要覆盖 this.customersUsuarios = [...this.customersUsuarios, ...data2];
内容的提问来源于stack exchange,提问作者Bryan Ortiz
相关产品推荐
相关产品推荐

