Si tengo algo como lo siguiente

<form #myForm="ngForm">
  <input *ngFor="let item of items; index as i" [name]="'input_' + i" [(ngModel)]="item" myValidationAttribute>
</form>

Y tengo una función que actualiza elementos y necesito esperar el formulario para actualizar antes de enviar el formulario

updateAndSubmit() {
  this.items = newItems;
  setTimeout(() => {
    if (this.myForm.valid) {
      // Do stuff with valid form
    }
  });
}

¿Es setTimeout como esta la forma preferida de esperar la actualización del DOM o hay algo en la línea de fixture.whenStable () utilizado en las pruebas unitarias?

SetTimeout simplemente no se siente bien, como si fuera un truco sucio.

Aquí hay un StackBlitz https://stackblitz.com/edit/angular-pv4tyb

0
Adrian Brand 3 dic. 2019 a las 04:52

2 respuestas

La mejor respuesta

Como dijo @Antediluvian, esto no es un truco, se trata de poner la devolución de llamada al final de la cola del evento, es decir, asegurarse de que el código en la devolución de llamada no se ejecute en el bucle de eventos actual, sino en el siguiente o posterior .

Dicho esto, si te encuentras haciendo algo como esto y necesitas especificar un retraso en el setTimeout, entonces tienes un problema, porque es poco probable que el retraso que utilices en el desarrollo funcione para todos los clientes.

En este caso, el setTimeout simple que está utilizando debería estar bien, y AFAIK, es "la forma en que se hace".

Entiendo que su código real es más complejo, pero en base a este ejemplo, considere que no necesita empujar ese valor adicional a través del formulario; solo puede obtener el valor del formulario y modificarlo directamente (o una copia del valor del formulario) para generar el valor que utiliza (para, por ejemplo, publicar en una API).

1
GreyBeardedGeek 3 dic. 2019 a las 03:15

Para mí, esto es 100% un caso de uso de formularios reactivos en lugar de formularios basados en plantillas:

<form [formGroup]="itemsFa">
  <input *ngFor="let item of itemsFa.controls; index as i" [name]="'input_' + i" [formControlName]="i">
</form>


constructor(private fb: FormBuilder) {
  this.itemsFa = this.fb.array([]);
}

updateAndSubmit() {
  this.itemsFa.clear();
  newItems.forEach(item => {
    const fc = new FormControl(item, [myValidator]); // convert validation directive to validator fn
    this.itemsFa.push(fc)
  });
  if (this.itemsFa.valid) {
    // Do stuff with valid form
  }
}

Ejemplo de blitz: https://stackblitz.com/edit /angular-h5rhgx?file=src%2Fapp%2Fapp.module.ts

0
bryan60 3 dic. 2019 a las 03:50