【问题标题】:How to bind array of inputs to model in Angular如何将输入数组绑定到Angular中的模型
【发布时间】:2019-05-09 13:01:45
【问题描述】:

有人可以帮助我使用以下代码并给我一个它不起作用的原因。我正在从字符串数组创建一系列输入,并且我想将每个输入值绑定到字符串数组中的相应插槽。似乎很标准,但我似乎没有抓住这个问题。

我尝试了以下两种情况,但 Colors 数组 (=string[]) 仍然为空!

<tr *ngFor="let color of Colors; let i = index;">
 <td>
  <mat-form-field>
      <input required matInput placeholder="Color ({{ i + 1}})"   [name]="'color_' + i" [(ngModel)]="color">
  </mat-form-field>
</td>
</tr>

<tr *ngFor="let color of Colors; let i = index;">
 <td>
  <mat-form-field>
   <input required matInput placeholder="Color ({{ i + 1}})"  [name]="'color_' + i" [(ngModel)]="Colors[i]">
  </mat-form-field>
</td>
</tr>

【问题讨论】:

  • 看看你在说什么[(ngModel)]="Colors[i]"?太傻了,就说[(ngModel)]="color"....你已经可以访问Colors[i],它是颜色......现在你可以给你看.ts文件吗?
  • [(ngModel)]="color" => 这是我尝试的第一个案例(第一个代码段),但并不成功
  • 对于代码:代码中唯一相关的是Colors数组的声明:Colors: string[] = []
  • 浏览器控制台有错误吗?
  • 不,完全没有错误

标签: arrays angular ngmodel


【解决方案1】:

字符串在 JavaScript 中是不可变的,这意味着我们不能将 ngModel 绑定到它们。您可以很容易地将数组转换为具有键颜色和字符串值的对象数组。这将解决您的绑定问题。这是一些代码。我还拼凑了一个 stackbitz 给你看。

不过,我会推荐 Joey gough 的回答。该代码感觉更正确,并且解决了这个问题的“角度方式”。 祝你好运!

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  Colors = [{color: 'stringColor1'}, {color: 'stringColor2'}]
}

<tr *ngFor="let item of Colors; let i = index;">
  {{i}}
 <td>
  <input required placeholder="Color ({{ i + 1}})" [name]="'color_' + i" [(ngModel)]="item.color">
</td>
</tr>

{{Colors | json}}

见: https://stackblitz.com/edit/angular-sj623x

【讨论】:

  • 完美解决方案:清晰、正确、有见地!非常感谢,乔纳斯!
  • 嘿乔纳斯,我太快了:你说'字符串在 JavaScript 中是不可变的,这意味着我们不能将 ngModel 绑定到它们。但是为什么我可以像 [(ngModel)]="companyname" 那样将 ngmodel-bind 绑定到一个字符串? (公司名称:字符串)
  • 因为您将它绑定到变量(这是类的属性)。在某种程度上,这基本上是一个参考/指针。抱歉,说这里的问题是字符串可能有点简化了。 “ngFor 默认使用对象标识来比较值,当使用原始值(数字、字符串、布尔值)时会中断,因为它们在修改时会改变标识)。” - 这基本上是对同一问题的更高级别的描述。 stackoverflow.com/questions/46991497/…
  • 这里也是一个很好的讨论主题:groups.google.com/forum/#!topic/angular/QgcRBpjiHAQ 他们当然也得出结论“字符串对象是不可变的,不能“编辑”字符串的值,你只能用另一个。" 这会导致问题,因为我们不能保持绑定到一个被删除的值,然后创建一个新的值。
【解决方案2】:

Afaik ngModel 要求变量是类的属性。

你应该尝试使用响应式表单

@Input() colors: string[];
public formGroup: FormGroup;
constructor(private formBuilder: FormBuilder) {
}

ngOnInit() {
  const formControls = {};
  this.colors.forEach(e => {
    formControls[e]: new FormControl(e);
  }
  this.formGroup = this.formBuilder.group(formControls);
}

然后在你的html中像这样}

<tr *ngFor="let color of Colors; let i = index;" [formGroup]="formGroup">
 <td>
  <mat-form-field>
      <input required matInput placeholder="Color ({{ i + 1}})"   [name]="'color_' + i" [formControlName]="color">
  </mat-form-field>
</td>
</tr>

我是即时写的,所以不知道它是否有效。但是应该进行一些调整。

【讨论】:

  • 谢谢!我知道还有其他方法可以解决这个问题。但这似乎与模板方法一致,并且非常干净。所以,这就是我问的原因。感谢您分享您的代码!
  • 这段代码是错误的:e =&gt; { formControls[e]你不能使用一个对象作为数组索引
  • @JBoy, colors 是一个字符串数组。所以e 是一个字符串。 formControls 是一个对象。所以,formControls[e] 在对象中使用字符串作为键。
【解决方案3】:

可以使用 [(ngModel)] 或 ReactiveForms。

如果你使用 [(ngModel)] 的问题是你不能迭代自己的数组。

//***WRONG**, you change "Colors" in input and is iterating over Colors
//you see that your form is "unestable"
<div *ngFor="let color of Colors; let i = index;">
   <input required matInput placeholder="Color ({{ i + 1}})"  [name]="'color_' + i" [(ngModel)]="Colors[i]">
</div>

但你可以使用

<tr *ngFor="let color of ' '.repeat(Colors.length).split(''); let i = index;">
 <td>
  <mat-form-field>
   <input required matInput placeholder="Color ({{ i + 1}})"  
               [name]="'color_' + i" [(ngModel)]="Colors[i]">
  </mat-form-field>
</td>
</tr>
<hr/>
{{Colors|json}}

是的,是一种解决方法:不迭代颜色,只迭代使用 String.repeat 和 split 动态创建的数组

' '.repeat(Colors.length).split('') //a string of same length that Colors.length

使用ReactiveForm,最好使用FormArray

<div *ngIf="formArray" [formGroup]="formArray">
<tr *ngFor="let control of formArray.controls;let i=index">
 <td>
  <mat-form-field>
   <input matInput placeholder="Color ({{ i + 1}})"  [name]="'color_' + i" [formControl]="control">
  </mat-form-field>
</td>
</tr>
</div>
<hr/>
{{formArray?.value|json}}

你可以看到stackblitz

【讨论】:

    【解决方案4】:

    您似乎忘记关闭“tr”标签。

    【讨论】:

    • 对不起,这只是上面的代码(我试图尽可能多地删除不相关的代码)。不过感谢您的反馈!
    • 我认为您应该尝试使用“p”标签而不是输入,看看它是否显示颜色数据。我认为您的问题可能是使用
    猜你喜欢
    • 2017-03-21
    • 2012-12-03
    • 1970-01-01
    • 2019-12-02
    • 2014-05-15
    • 1970-01-01
    • 2015-12-01
    • 1970-01-01
    • 2017-03-13
    相关资源
    最近更新 更多