Angolare 2: itera sui controlli della forma reattiva


97

Vorrei markAsDirtytutti i controlli all'interno di un file FormGroup.

Risposte:


199

Ho scoperto che Object.keyspuò gestire questo ..

    Object.keys(this.form.controls).forEach(key => {
      this.form.get(key).markAsDirty();
    });

Per Angular 8+, usa quanto segue (basato sulla risposta di Michelangelo):

    Object.keys(this.form.controls).forEach(key => {
      this.form.controls[key].markAsDirty();
    });

2
Quando utilizzo questa funzione in onSubmit ricevo l'errore Cannot invoke an expression whose type lacks a call signature. Type 'AbstractControl' has no compatible call signatures.Qualcuno sa perché?
maidi

1
Object.keys (this.registerForm.controls) .forEach (key => {this.registerForm.controls [key] .markAsDirty ();});
Foad

Quando provo Object.keys o anche "for in", non ottengo nulla. Tuttavia, se console.log (form.controls) posso VEDERE tutti i vari controlli del form contenuti con l'oggetto. Sono sconcertato.
Jake Shakesworth

Utilizzando Angular 5, markAsDirty () / markAsTouched () non ricorre in alcun sotto-FormGroup. Ho suddiviso il codice sopra in una funzione ricorsiva e l'ho chiamato su qualsiasi sotto-FormGroup. Funziona meglio con l'attuale progetto dell'interfaccia utente di Angular Material nel caso in cui un utente non tocchi mai un elemento richiesto, lo chiamo quando l'utente tenta di inviare il modulo per contrassegnare uno qualsiasi in quel punto.
Robert

3
Grazie per aver letto il mio post e aver aggiornato la tua risposta. Anche i documenti ufficiali sono obsoleti, quindi ho dovuto capirlo stampando ogni riga ...
Michelangelo

56

Per quello che vale, c'è un altro modo per farlo senza dover usare la magia Object.keys (...) :

for (const field in this.form.controls) { // 'field' is a string

  const control = this.form.get(field); // 'control' is a FormControl  

}

come ottenere l'indice del ciclo?
SVK

1
Per coloro che utilizzano TSLint, il codice funziona, ma TSLint si lamenta con "le istruzioni for (... in ...) devono essere filtrate con un'istruzione if (forin)".
Yennefer

1
tslint sta precisando, una citazione dalla documentazione JavaScript del for ... in dichiarazione stackoverflow.com/questions/40770425/...
Egle Kreivyte

41

La risposta accettata è corretta per una struttura a modulo piatto, ma non risponde completamente alla domanda originale. Una pagina web può richiedere FormGroup e FormArrays annidati e dobbiamo tenerne conto per creare una soluzione robusta.

public markControlsDirty(group: FormGroup | FormArray): void {
    Object.keys(group.controls).forEach((key: string) => {
        const abstractControl = group.controls[key];

        if (abstractControl instanceof FormGroup || abstractControl instanceof FormArray) {
            this.markControlsDirty(abstractControl);
        } else {
            abstractControl.markAsDirty();
        }
    });
}

funzionerà instanceofsempre dopo essere stato trasferito da Typescript?
il notevole

@ the-notable instanceofnon è una parola chiave specifica di TypeScript ( developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… ) Nemmeno il classtipo di dati.
Keenan Diggs

8

Usando la risposta di @Marcos ho creato una funzione che può essere chiamata passando un formGroup come parametro e contrassegna ogni controllo figlio di formGroup come sporco, solo per renderlo utilizzabile da più punti attorno al codice inserendolo all'interno di un servizio, ad esempio.

public touchAllFormFields(formGroup: FormGroup): void {
    Object.keys(formGroup.controls).forEach((key) => {
        formGroup.get(key).markAsDirty();
    });
}

spero che sia d'aiuto ;)


Perfetto! Aggiunto al servizio, insieme a funzioni simili a clearValidators, untouch, ecc. Potrebbe essere necessario aggiungere un controllo ricorsivo per i controlli annidati, ma per ora funziona. Grazie!
mc01

6

Sembra che la get funzione non funzioni più per il recupero di valori specifici nel modulo in Angular 8, quindi è così che l'ho risolto in base alla risposta di @Liviu Ilea.

for (const field in this.myForm.controls) { // 'field' is a string
  console.log(this.myForm.controls[field].value);
}

Sei sicuro? Il documento API ha già il metodo get per Abstract Control ( angular.io/api/forms/AbstractControl#get ). Non sono ancora migrato. Now I'm scared (⊙_ ◎)
Alan Grosz

@AlanGrosz Sì, l'ho visto anche io quando lo stavo riscrivendo ma anche stampando tutte le righe nella console non sono riuscito a trovare alcun metodo get sull'oggetto. Penso che la documentazione sia dietro. Buona fortuna durante la migrazione!
Michelangelo

Non penso che l'abbiano rimosso, ottengono lavori per me in Angular 8. Inoltre è ancora nella documentazione angular.io/api/forms/AbstractControl#get
Laszlo Sarvold

5

    Object.keys( this.registerForm.controls).forEach(key => {
       this.registerForm.controls[key].markAsDirty();
    });


4

Questo è ciò che funziona per me

private markFormGroupTouched(formGroup: FormGroup) {
  Object.keys(formGroup.controls).forEach((key) => {
    const control = formGroup.controls[key];
    control.markAsDirty();
    if ((control instanceof FormGroup)) {
      this.markFormGroupTouched(control);
    }
  });
}

1

Creo questa funzione per renderlo * Ho un controllo con nome "order" e gli passo l'indice.

{"conditionGroups": [
   {
     "order": null,
     "conditions": []
   }
  ]
}


updateFormData() {
    const control = <FormArray>this.form.controls['conditionGroups'];  
    control.value.map((x,index)=>{
    x.order = index; 
 })
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.