¿Podría alguien ayudarme con el siguiente código y darme una razón por la que no funciona? Estoy creando una serie de entradas de una matriz de cadenas y quiero vincular cada valor de entrada a su ranura correspondiente en la matriz de cadenas. Parece ser bastante estándar, pero parece que no entiendo el problema.

He intentado los siguientes dos casos, ¡pero la matriz Colors (= string []) permanece vacía!

<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>
0
MuseOfMusic 9 may. 2019 a las 16:01

4 respuestas

La mejor respuesta

Las cadenas son inmutables en JavaScript, lo que significa que no podemos vincular ngModel a ellas. Podría convertir fácilmente su matriz en una matriz de objetos con el color clave y el valor de sus cadenas. Esto solucionaría su problema vinculante. Aquí hay un código. También pirateé un stackbitz para mostrarte.

Sin embargo, recomendaría la respuesta de Joey Gough. Ese código se siente más correcto y "la forma angular" de resolver esto. ¡Buena suerte!

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}}

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

0
Jonas Johansson 9 may. 2019 a las 13:31

Afaik ngModel requiere que la variable sea una propiedad de la clase.

Deberías intentar usar formas reactivas

@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);
}

Luego en tu html algo como esto}

<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>

Escribí eso sobre la marcha, así que no sé si funciona. Pero con algunos ajustes, debería.

1
Joey Gough 9 may. 2019 a las 13:21

Es posible usar [(ngModel)] en formularios reactivos.

El problema si usa [(ngModel)] es que no puede iterar sobre la propia matriz.

//***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>

Pero puedes usar

<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}}

Sí, es una solución alternativa: no iterar sobre colores, solo sobre una matriz creada sobre la marcha usando String.repeat y split

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

Usando ReactiveForm, es mejor usar un 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}}

Puede ver el stackblitz

1
Eliseo 9 may. 2019 a las 16:50

Parece que olvidó cerrar la etiqueta "tr".

0
Mohammadreza Imani 9 may. 2019 a las 13:09