在更改时更新选择元素数据

时间:2021-02-24 21:15:11

标签: angular typescript angular-material

我有两个选择,其中一个选择您选择汽车,另一个选择您通过获取请求获得该汽车的特定型号。但是当您取消选中第一个选择数据的选项时,第二个选择仍然存在,我该如何更新数据?。

.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];
        });
        })
  }

2 个答案:

答案 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,这样会更好。