【问题标题】:How to use ngModel inside *ngFor with index?如何在 *ngFor 中使用带有索引的 ngModel?
【发布时间】:2020-06-18 13:23:12
【问题描述】:

我正在使用*ngFor 生成动态mat-inputs。我想使用*ngFor 元素的索引将每个[(ngModel)] 值存储在不同的数组中(不是*ngFor 一个)。这就是我正在做的事情:

<div  *ngFor="let item of items;let id = index;">

<mat-form-field >
  <mat-select  [(ngModel)]="differentArray[id].first"  (ngModelChange)="onSelection()">
    <mat-option *ngFor="let number of arrayOfNumbers" [value]="number">{{number}}</mat-option>
  </mat-select>
</mat-form-field> 

<mat-form-field>
  <mat-select  [(ngModel)]="differentArray[id].second"  (ngModelChange)="onSelection()">
    <mat-option *ngFor="let number of arrayOfNumbers" [value]="number" >{{number}}</mat-option>
  </mat-select>
</mat-form-field>

<mat-form-field >
  <mat-select  [(ngModel)]="differentArray[id].third"  (ngModelChange)="onSelection()">
    <mat-option *ngFor="let number of arrayOfNumbers" [value]="number">{{number}}</mat-option>
  </mat-select>
</mat-form-field>

</div>

但所有不同*ngFor 的值都变得相同。为什么会这样?我怎样才能正确地使用每个元素 id 做到这一点?

【问题讨论】:

  • 您对所有选择输入使用相同的 onSelection() 方法。也许这个方法有什么东西?
  • 没有。他们什么都没有发生。到现在为止只是 console.log。
  • 你能分享一个例子来说明But the values for all different *ngFor are getting same 的含义吗?看起来你 *ngFor 在同一个数组上 3 次。
  • 您使用differentArray 的方式很奇特。你能分享一下你是怎么定义它的吗?
  • 我有一个items 数组,对于每个item,我必须取这三个下拉值。然后,我必须根据itemsitem 的索引将这三个值保存在不同的数组中。所以基本上,我必须将 ngfor 中的所有项目保存为 differentArray=[{first:"selected value from dropdown",second:"selected value from ddropdown",third:"selected value from dropdown"},{},{},{}] 。但是 differentArray 的每个对象都得到相同的值。

标签: angular typescript forms ngfor


【解决方案1】:

从您定义属性绑定到[(ngModel)] 指令的方式来看,differentArray 应该采用以下形式

differentArray = [
  { first: 0, second: 0, third: 0 },
  { first: 0, second: 0, third: 0 },
  { first: 0, second: 0, third: 0 }
]

工作示例:Stackblitz

更新

您可以将@Input() 装饰器绑定到setter 并直接在子级中初始化differentArray,而不是将其推送到父级中。但是不管你是在parent还是child中做的,最重要的要记住的是对象会被引用推送。因此,对其中一个对象的任何更改也会影响其他对象。所以你需要使用JSON.parse(JSON.stringify(obj)) 来创建obj 的深层克隆。试试下面的

parent.component.ts

export class ParentComponent {
  items = ['item1', 'item2', 'item3'];
  arrayOfNumbers = [1, 2, 3, 4, 5];
  differentArray = { first: 0, second: 0, third: 0 };

  constructor() {}
}

parent.component.html

<app-child [items]="items" [arrayOfNumbers]="arrayOfNumbers" [differentArray]="differentArray"></app-child>

child.component.ts

export class ChildComponent {
  _differentArray: Array<any> = [];

  @Input() items: Array<any> = [];
  @Input() arrayOfNumbers: Array<any> = [];
  
  @Input() set differentArray(obj: any) {
    this.items.forEach(item => 
      // notice the deep clone using `JSON.parse(JSON.stringify(obj)` here
      this._differentArray.push(JSON.parse(JSON.stringify(obj)))
    );
  }

  constructor() {}

  onSelection() {
    console.log('selected: ', this._differentArray);
  }
}

child.component.html

<div *ngFor="let item of items; let id=index;">
  <mat-form-field >
    <mat-select  [(ngModel)]="_differentArray[id].first"  (ngModelChange)="onSelection(id)">
      <mat-option *ngFor="let number of arrayOfNumbers" [value]="number">{{number}}</mat-option>
    </mat-select>
  </mat-form-field> 

  <mat-form-field>
    <mat-select  [(ngModel)]="_differentArray[id].second"  (ngModelChange)="onSelection(id)">
      <mat-option *ngFor="let number of arrayOfNumbers" [value]="number" >{{number}}</mat-option>
    </mat-select>
  </mat-form-field>

  <mat-form-field >
    <mat-select  [(ngModel)]="_differentArray[id].third"  (ngModelChange)="onSelection(id)">
      <mat-option *ngFor="let number of arrayOfNumbers" [value]="number">{{number}}</mat-option>
    </mat-select>
  </mat-form-field>
</div>

工作示例:Stackblitz

【讨论】:

  • 显然我正在使用的 diffferentArray 是从父级动态生成并通过 @Input() 发送的。而且这种方法不适用于此。我已经以与您相同的方式定义了数组。我尝试了和你一样的定义静态数组,它有效。
  • 你能展示从父级传入的数组的外观吗?然后我们可以尝试修改child中的ngModel绑定。
  • differentArray =[{first: 1, second: 0, third: 0}]items 数组(在 *ngFor 中使用的那个)在父级增加,我不断将 {first: 1, second: 0, third: 0} 推到 differentArray 上并将其传递给孩子。
  • 我可能已经找到了答案。对象是通过引用分配的,因此对一个对象的任何更改也会修改其他对象。您可以使用JSON.parse(JSON.stringify(obj)) 创建一个深度关闭。我已经更新了答案。
  • 我试过了,不幸的是这不起作用,因为在你的情况下,数组已经定义了,但在我的情况下它们是动态的。所以我认为@Input() 发生在 items 数组为空时。因此,在发生任何事情之前,它会尝试进入 forEach 内部,因此不起作用。现在,当第一个 item 被推送到 items 时,它就被定义了,但什么也没发生,因为它只是一个引用。这是我尝试从父母那里获得differentArray 的唯一原因。
猜你喜欢
  • 2017-10-28
  • 2017-05-29
  • 2021-06-02
  • 2021-06-11
  • 2021-09-12
  • 2016-10-11
  • 2019-12-16
  • 2020-08-09
  • 2019-03-16
相关资源
最近更新 更多