Kątowy 2: Iteruj po reaktywnych kontrolkach formularza

97

Chciałbym markAsDirtywszystkie elementy sterujące wewnątrz pliku FormGroup.

Marcos JC Kichel
źródło

Odpowiedzi:

198

Okazało się, że Object.keyssobie z tym poradzę

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

W przypadku Angular 8+ użyj następującego (na podstawie odpowiedzi Michała Anioła):

    Object.keys(this.form.controls).forEach(key => {
      this.form.controls[key].markAsDirty();
    });
Marcos JC Kichel
źródło
2
Kiedy używam tej funkcji w onSubmit, pojawia się błąd. Cannot invoke an expression whose type lacks a call signature. Type 'AbstractControl' has no compatible call signatures.Czy ktoś wie dlaczego?
maidi
1
Object.keys (this.registerForm.controls) .forEach (key => {this.registerForm.controls [klucz] .markAsDirty ();});
Foad
Kiedy próbuję Object.keys lub nawet „for in”, nic nie dostaję. Jednak jeśli korzystam z console.log (form.controls), mogę ZOBACZYĆ wszystkie różne kontrolki formularza zawarte w obiekcie. Jestem zdumiony.
Jake Shakesworth
Używając Angular 5, markAsDirty () / markAsTouched () nie powtarza się w żadnych sub-FormGroups. Przekształciłem powyższy kod w funkcję rekurencyjną i wywołałem go na dowolnych sub-FormGroups. Działa lepiej z bieżącym projektem Angular Material UI na wypadek, gdyby użytkownik nigdy nie dotknął wymaganego elementu, nazywam to, gdy użytkownik próbuje przesłać formularz, aby zaznaczyć dowolny w tym momencie.
Robert,
3
Dziękuję za przeczytanie mojego postu i zaktualizowanie własnej odpowiedzi. Oficjalne dokumenty również są nieaktualne, więc musiałem to rozgryźć, drukując każdą linię ...
Michelangelo
56

Warto, jest inny sposób na zrobienie tego bez konieczności używania magii Object.keys (...) :

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

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

}
Liviu Ilea
źródło
jak uzyskać indeks pętli?
SVK
1
Dla tych, którzy używają TSLint, kod działa, ale TSLint narzeka, że ​​„instrukcje for (... in ...) muszą być filtrowane za pomocą instrukcji if (forin)”.
Yennefer
1
tslint wskazuje, cytat z dokumentacji JavaScript instrukcji for ... in stackoverflow.com/questions/40770425/ ...
Egle Kreivyte
41

Przyjęta odpowiedź jest prawidłowa dla płaskiej konstrukcji formy, ale nie odpowiada w pełni na pierwotne pytanie. Strona internetowa może wymagać zagnieżdżonych FormGroups i FormArrays i musimy wziąć to pod uwagę, aby stworzyć solidne rozwiązanie.

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();
        }
    });
}
Keenan Diggs
źródło
będzie instanceofzawsze działać po transpozycji przez maszynopis?
znaczący
@ the-notable instanceofnie jest słowem kluczowym specyficznym dla języka TypeScript ( developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… ) Nie jest też classtypem danych.
Keenan Diggs
8

Korzystając z @Marcos answer, stworzyłem funkcję, którą można nazwać przekazując parametr formGroup jako parametr i zaznacza ona wszystkie kontrolki podrzędne formGroup jako brudne, aby umożliwić jej użycie z większej liczby miejsc w kodzie, na przykład umieszczając ją w usłudze.

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

mam nadzieję, że to pomoże ;)

Hugo
źródło
Idealny! Dodano do usługi, wraz z podobnymi funkcjami do clearValidators, untouch itp. Może chcieć dodać rekurencyjne sprawdzanie zagnieżdżonych kontrolek, ale to działa na razie. Dzięki!
mc01
6

Wygląda na to, że get funkcja nie działa już przy pobieraniu określonych wartości w formularzu w Angular 8, więc tak to rozwiązałem na podstawie odpowiedzi @Liviu Ilea.

for (const field in this.myForm.controls) { // 'field' is a string
  console.log(this.myForm.controls[field].value);
}
Michał Anioł
źródło
Jesteś pewny? Dokumentacja API ma już metodę get dla Abstract Control ( angular.io/api/forms/AbstractControl#get ). Jeszcze nie migrowałem. Teraz się boję (⊙_ ◎)
Alan Grosz
@AlanGrosz Tak, też to widziałem, przepisując to, ale nawet podczas drukowania wszystkich linii w konsoli nie mogłem znaleźć metody get na obiekcie. Myślę, że dokumentacja jest w tyle. Powodzenia w migracji!
Michelangelo
Nie sądzę, żeby go usunęli, zdobądź dla mnie prace w Angular 8. Również jest nadal w dokumentacji angular.io/api/forms/AbstractControl#get
Laszlo Sarvold
5

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

Foad
źródło
4

To właśnie działa dla mnie

private markFormGroupTouched(formGroup: FormGroup) {
  Object.keys(formGroup.controls).forEach((key) => {
    const control = formGroup.controls[key];
    control.markAsDirty();
    if ((control instanceof FormGroup)) {
      this.markFormGroupTouched(control);
    }
  });
}
omyfish
źródło
1

Tworzę tę funkcję, aby * * Mam kontrolkę z nazwą 'order' i przekazałem mu indeks.

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


updateFormData() {
    const control = <FormArray>this.form.controls['conditionGroups'];  
    control.value.map((x,index)=>{
    x.order = index; 
 })
João Marcos Santos Teixeira
źródło