我有两个选择,其中一个选择您选择汽车,另一个选择您通过获取请求获得该汽车的特定型号。但是当您取消选中第一个选择数据的选项时,第二个选择仍然存在,我该如何更新数据?。
.html
<mat-form-field appearance="fill">
<mat-select multiple formControlName="Brand" (selectionChange)="getModels($event)" #multiSelect>
<mat-option *ngFor="let item of vehicles" [value]="item">{{item}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-select multiple formControlName="Model">
<mat-option *ngFor="let item of inputValue" [value]="item">{{item}}</mat-option>
</mat-select>
</mat-form-field>
.ts
this.campaignService.getVehicles().subscribe((data: any[])=>{
this.vehicles = data;
console.log(data);
})
// get car models
getModels(event: any) {
let value = event.value;
value.forEach((item: any) => {
this.campaignService.getModels(item).subscribe((data: any[])=>{
console.log(data);
this.inputValue = [...this.inputValue, ...data];
});
})
}
答案 0 :(得分:2)
.当你使用这个时:
this.inputValue = [...this.inputValue, ...data];
this.inputValue 的值是以前的值 + 数据(新模型)
所以你应该尝试添加这个:
this.inputValue = [];
在 value.forEach 后面是这样的:
getModels(event: any) {
let value = event.value;
this.inputValue = [];
value.forEach((item: any) => {
this.campaignService.getModels(item).subscribe((data: any[])=>{
console.log(data);
this.inputValue = [...this.inputValue, ...data];
});
})
}
这应该可行,但是,您将向您的 api 发出多个请求,我认为这不是一个好主意。您可以尝试将时间对象与数组数据一起保存在本地,当您取消选中某个选项时,请从 this.inputValue 中删除此数据。
答案 1 :(得分:2)
这是我将如何做到这一点。由于我不知道你的数据是什么形状,我只是创建了一些,你必须适应你的情况。
请注意@barrilocho 的答案是正确的,但您的问题是您使用了错误的事件。
每次检查项目时都会触发您的 selectionChange
,所有检查项目都在其事件值中,因此 http 调用会累积。
尝试以这种方式使用 closed
事件:
<mat-select multiple (closed)="getModels(cars.value)" #cars>
Is 仅在面板关闭时触发,因此会遍历您选中的项目。如果您有大量数据,closed
事件只是针对更大问题的小优化。
Repro on Stackblitz 代码如下:
服务:
getModel(car: string) {
const models = [
{ car: "car1", model: "model1" },
{ car: "car2", model: "model2" },
{ car: "car3", model: "model3" },
{ car: "car3", model: "model4" }
];
// Could be a filter, adapt as you wish
return of(models.filter(m => m.car === car));
}
TS:
export class SelectValueBindingExample {
vehicles = ["car1", "car2", "car3"];
models$: Observable<Array<any>>;
constructor(private _modelsService: ModelsService) {}
getModels(selectedCars: Array<any>) {
const obs$: Array<Observable<any>> = [];
// Would be better if you could find a way to only request the new items and remove the unckecked ones
selectedCars.forEach(car => obs$.push(this._modelsService.getModel(car)));
this.models$ = forkJoin(obs$).pipe(
map(values => values.flat()) // flatten an array of array
);
}
}
HTML:
<mat-form-field appearance="fill">
<mat-label>Choose your cars</mat-label>
<mat-select multiple (selectionChange)="getModels(cars.value)" #cars>
<mat-option *ngFor="let item of vehicles" [value]="item">
{{item}}
</mat-option>
</mat-select>
</mat-form-field>
<br /><br />
<mat-form-field appearance="fill">
<mat-label>Choose your model</mat-label>
<mat-select multiple (onClose)="getModels($event)">
<mat-option *ngFor="let model of models$ | async" [value]="model">
{{model.car}} - {{model.model}}
</mat-option>
</mat-select>
</mat-form-field>
这里我给你一个直接使用observable
的解决方案(注意html中的async pipe
)。这就是我的做法,但首先,如果可能的话,我建议重新设计您的 campainService.getModels
方法,以实际接受多个项目并在后端处理所有内容。每次更改只会调用一次 http,这样会更好。