Kątowy 2: Iteruj po reaktywnych kontrolkach formularza


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

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  

}

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

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


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

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


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

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; 
 })
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.