1

有问题的代码 ts 部分:

    import { Component } from '@angular/core';
    import { FormControl } from '@angular/forms';
    
    @Component({
      selector: 'my-app',
      templateUrl: './app.component.html'
    })
    export class AppComponent {
      constructor() {}
      fields = [null, null];
      countries: any = [
        {
          full: 'Great Britain',
          short: 'GB'
        },
        {
          full: 'United States',
          short: 'US'
        },
        {
          full: 'Canada',
          short: 'CA'
        }
      ];
    }

有问题的代码html部分:

    <div *ngFor="let f of fields; let i = index">
      <mat-form-field>
        <mat-select name="countryString" [(ngModel)]="fields[i]" placeholder="Country">
          <mat-option *ngFor="let item of countries" [value]="item.short">{{item.full}}</mat-option>
        </mat-select>
      </mat-form-field>
    </div>

是我在 stackblitz 上的示例。

基本思想如下:

  • 有一个字符串数组
  • 最初,该数组包含固定数量的元素,但具有空值
  • 我们想给元素赋值,所以我们遍历它们,并将它们绑定到一个 mat select 组件

当我们要选择第一个元素时,问题就开始了,因为当您选择它时,第二个组件也获取了该属性。有趣的是,数组的第二个元素没有获得值,但绑定的 mat-select 组件切换到该元素。

正如你所看到的,我写了一个没有 ngFor 部分的工作版本,它的工作方式就像一个魅力,所以我的问题是这里的问题是什么?是材料设计缺陷还是我犯了一些错误?

4

1 回答 1

1

发生这种情况是因为 ngFor 将数组中的项目视为相同,并正在比较它们以找到它应该替换的模板。因此,当值相同时,指令会为所选值标记出新模板并替换两个匹配项,因为该值是它唯一需要比较的内容。您可以尝试在数组中使用一个对象,这样模板就不会像这样重新渲染:

  fields = [{
    value: null
  }, {
    value: null
  }];
<div *ngFor="let f of fields; let i = index">
  <mat-form-field>
    <mat-select name="countryString" [(ngModel)]="fields[i].value" placeholder="Country">
      <mat-option *ngFor="let item of countries" [value]="item.short">{{item.full}}</mat-option>
    </mat-select>
  </mat-form-field>
</div>

这样,ngFor 中的对象始终是相同的,并且避免了重新呈现模板,但允许您更改该索引处的特定值。

或者使用 trackBy 并使用索引来跟踪模板:

  trackBy(index, val) {
    return index
  }
<div *ngFor="let f of fields; let i = index; trackBy: trackBy">

这里的例子

于 2021-09-02T08:38:05.837 回答