Jak znaleźć nieprawidłowe kontrolki w formie reaktywnej kątowej 4


89

Mam formularz reaktywny w Angular jak poniżej:

this.AddCustomerForm = this.formBuilder.group({
    Firstname: ['', Validators.required],
    Lastname: ['', Validators.required],
    Email: ['', Validators.required, Validators.pattern(this.EMAIL_REGEX)],
    Picture: [''],
    Username: ['', Validators.required],
    Password: ['', Validators.required],
    Address: ['', Validators.required],
    Postcode: ['', Validators.required],
    City: ['', Validators.required],
    Country: ['', Validators.required]
});

createCustomer(currentCustomer: Customer) 
{
    if (!this.AddCustomerForm.valid)
    {
        //some app logic
    }
}

this.AddCustomerForm.valid zwraca wartość false, ale wszystko wygląda dobrze.

Próbowałem znaleźć, sprawdzając właściwość statusu w kolekcji formantów. Ale zastanawiam się, czy istnieje sposób na znalezienie nieprawidłowych i wyświetlenie ich użytkownikowi?


Jeśli chcesz tylko wyświetlić pola z błędem, możesz użyć css, aby podświetlić lub pokolorować nieprawidłowe pola. Każde nieprawidłowe pole ma klasę „ng-invalid” dołączoną do listy klas
— LookForAngular,

Odpowiedzi:


168

Możesz po prostu powtórzyć każdą kontrolę i sprawdzić status:

public findInvalidControls() {
    const invalid = [];
    const controls = this.AddCustomerForm.controls;
    for (const name in controls) {
        if (controls[name].invalid) {
            invalid.push(name);
        }
    }
    return invalid;
}

1
dzięki za to ale próbowałem tego i nawet to nic nie zwraca, mój formularz jest nadal nieważny, to jest dziwne. Mam na myśli, że ten kod wygląda dobrze, ale nie ma sensu, dlaczego form.valid zwraca false
— sa_

co findInvalidControls()ci zwraca
— Max Koretskyi

1
nic nie zwraca, nieważne jest puste. Sprawdziłem jeden po drugim na ekranie debugowania, wszystkie kontrolki są prawidłowe, ale this.AddCustomerForm.valid nadal zwraca wartość false.
— sa_

Chyba się dowiedziałem. jest pole e-mail i wyrażenie regularne, ale w jakiś sposób status kontrolki jest OCZEKUJĄCY i może być przyczyną
— sa_

6
@ AngularInDepth.com - jeśli jedna z kontrolek jest grupą formularzy, funkcja zwróci nieprawidłową grupę formularzy, a nie określoną kontrolkę formularza, która jest nieprawidłowa
— John Smith

35

Właśnie walczyłem z tym problemem: każde pole formularza jest prawidłowe, ale sam formularz jest nieprawidłowy.

Okazuje się, że ustawiłem 'Validator.required' na FormArray, gdzie kontrolki są dodawane / usuwane dynamicznie. Więc nawet jeśli FormArray był pusty, nadal był wymagany i dlatego formularz był zawsze nieprawidłowy, nawet jeśli wszystkie widoczne kontrolki zostały poprawnie wypełnione.

Nie znalazłem nieprawidłowej części formularza, ponieważ moja funkcja `` findInvalidControls '' sprawdzała tylko FormControl, a nie FormGroup / FormArray. Więc trochę to zaktualizowałem:

/* 
   Returns an array of invalid control/group names, or a zero-length array if 
   no invalid controls/groups where found 
*/
public findInvalidControlsRecursive(formToInvestigate:FormGroup|FormArray):string[] {
    var invalidControls:string[] = [];
    let recursiveFunc = (form:FormGroup|FormArray) => {
      Object.keys(form.controls).forEach(field => { 
        const control = form.get(field);
        if (control.invalid) invalidControls.push(field);
        if (control instanceof FormGroup) {
          recursiveFunc(control);
        } else if (control instanceof FormArray) {
          recursiveFunc(control);
        }        
      });
    }
    recursiveFunc(formToInvestigate);
    return invalidControls;
  }

3
Niezwykle przydatna odpowiedź. Dziękuję bardzo
— Mikki

1
Zgadzam się, bardzo przydatna odpowiedź.
— nenea

20

W sekcji DevTools w Chrome wybierz kartę Console.

W konsoli wpisz polecenie:

document.getElementsByClassName('ng-invalid')

Wynik powinien być podobny do tego: wprowadź opis obrazu tutaj

W tym przypadku podkreślony tekst dotyczy kontrolki formularza listen-address. Otoczony tekst: .ng-invalidwskazuje, że formant jest nieprawidłowy.

Uwaga: testowane w chromie


2
wydaje mi się to najbardziej bezpośrednią drogą odpowiedzi na to pytanie.
— ckapilla

2
Uratowałeś mnie od szaleństwa, gdybym tylko mógł kupić ci drinka
— Adam Winnipass

3

Zarówno formularze, jak i wszystkie kontrolki rozszerzają klasę kątową AbstractControl. Każda implementacja ma metodę dostępu do błędów walidacji.

let errors = this.AddCustomerForm.errors
// errors is an instance of ValidatorErrors

Dokumentacja API zawiera wszystkie odniesienia https://angular.io/api/forms/AbstractControl

Edytować

Myślałem, że akcesor błędu działał w ten sposób, ale ten link do github pokazuje, że są inni ludzie, którzy myśleli tak samo jak ja https://github.com/angular/angular/issues/11530

W każdym przypadku za pomocą metody dostępu do formantów można iterować po wszystkich formControls w formularzu.

Object.keys(this.AddCustomerForm.controls)
    .forEach( control => {
        //check each control here
        // if the child is a formGroup or a formArray
        // you may cast it and check it's subcontrols too
     })

1
zwraca to wartość null, nawet jeśli kontrolki są puste
— sa_

1
Powinien zwrócić wartość null, gdy nie ma błędów. Czy możesz opublikować swój szablon?
— LookForAngular

Tak, to nie zadziała, różne walidacje ustawione w każdej kontrolce formularza, te kontrolki formularza zawierają błędy, a formularz nie. Musisz powtórzyć sterowanie, tak jak Maximus dał odpowiedź.
— AJT82

Mogę uzyskać dostęp do błędów dla poszczególnych kont, takich jak this.form.controls ['Email']. Errors
— Nazrul Muhaimin

@ AJT_82 rzeczywiście sam formularz może wyświetlać błędy, jeśli walidator został ustawiony dla formGroup (sprawdź dokumenty dotyczące walidacji krzyżowej, która ma sens, aby sprawdzić w grupie, a nie w
— kontrolce

3

Teraz, w Angular 9, możesz użyć metody markAllAsTouched () do pokazania walidatorów nieprawidłowych kontrolek:

this.AddCustomerForm.markAllAsTouched();

Zamierzam dać temu +1, ponieważ pomogło mi to dowiedzieć się, co muszę wiedzieć - co oznacza wyświetlenie komunikatów weryfikacyjnych, gdy użytkownik niekoniecznie dotknął danych wejściowych.
— Sean Halls

1

Jeśli nie masz zbyt wielu pól w formularzu, możesz po prostu F12 i najechać kursorem na kontrolkę, zobaczysz wyskakujące okienko z nieskazitelnymi / dotkniętymi / prawidłowymi wartościami pola- "# nazwa_pola.form-control.ng- untouched.ng-invalid ”.


1

Myślę, że powinieneś spróbować użyć this.form.updateValueAndValidity()lub spróbować wykonać tę samą metodę w każdym z elementów sterujących.


1

Spróbuj tego

 findInvalidControls(f: FormGroup) {
    const invalid = [];
    const controls = f.controls;
    for (const name in controls) {
      if (controls[name].invalid) {
        invalid.push(name);
      }
    }
    return invalid;
  }

1

Spowoduje to zarejestrowanie wszystkich nazw kontrolek 😊

for (let el in this.ReactiveForm.controls) {
      if (this.ReactiveForm.controls[el].errors) {
        console.log(el)
      }
 }          

możesz zrobić z tego tablicę lub łańcuch i wyświetlić ją użytkownikowi


0

Pozwoliłem sobie poprawić kod AngularInDepth.com -s, tak aby rekurencyjnie wyszukiwał również nieprawidłowe dane wejściowe w zagnieżdżonych formularzach. Czy będzie zagnieżdżony przez FormArray-s lub FormGroup-s. Po prostu wprowadź formGroup najwyższego poziomu, a zwróci wszystkie elementy FormControls, które są nieprawidłowe.

Możesz ewentualnie przejrzeć niektóre z kontroli typu „instanceof”, jeśli oddzieliłbyś kontrolę FormControl i dodanie do funkcji nieprawidłowej tablicy w osobnej funkcji. To sprawiłoby, że funkcja wyglądałaby o wiele bardziej czysto, ale potrzebowałem globalnej, pojedynczej funkcji, opcji, aby uzyskać płaską tablicę wszystkich nieprawidłowych formControls i to jest rozwiązanie!

findInvalidControls( _input: AbstractControl, _invalidControls: AbstractControl[] ): AbstractControl[] {
    if ( ! _invalidControls ) _invalidControls = [];
    if ( _input instanceof FormControl  ) {
        if ( _input.invalid ) _invalidControls.push( _input );
        return _invalidControls;
    }

    if ( ! (_input instanceof FormArray) && ! (_input instanceof FormGroup) ) return _invalidControls;

    const controls = _input.controls;
    for (const name in controls) {
        let control = controls[name];
        switch( control.constructor.name )
        {
            case 'AbstractControl':
            case 'FormControl':
                if (control.invalid) _invalidControls.push( control );
                break;

            case 'FormArray':
                (<FormArray> control ).controls.forEach( _control => _invalidControls = findInvalidControls( _control, _invalidControls ) );
                break;

            case 'FormGroup':
                _invalidControls = findInvalidControls( control, _invalidControls );
                break;
        }
    }

    return _invalidControls;
}

Tylko dla tych, którzy tego potrzebują, więc nie muszą sami kodować.

Edytuj nr 1

Zażądano, aby zwracał również nieprawidłowe FormArray-s i FormGroups, więc jeśli tego również potrzebujesz, użyj tego kodu

findInvalidControls( _input: AbstractControl, _invalidControls: AbstractControl[] ): AbstractControl[] {
    if ( ! _invalidControls ) _invalidControls = [];
    if ( _input instanceof FormControl  ) {
        if ( _input.invalid ) _invalidControls.push( _input );
        return _invalidControls;
    }

    if ( ! (_input instanceof FormArray) && ! (_input instanceof FormGroup) ) return _invalidControls;

    const controls = _input.controls;
    for (const name in controls) {
        let control = controls[name];
        if (control.invalid) _invalidControls.push( control );
        switch( control.constructor.name )
        {    
            case 'FormArray':
                (<FormArray> control ).controls.forEach( _control => _invalidControls = findInvalidControls( _control, _invalidControls ) );
                break;

            case 'FormGroup':
                _invalidControls = findInvalidControls( control, _invalidControls );
                break;
        }
    }

    return _invalidControls;
}

1
Próbowałem, ale nie znalazłem żadnych nieprawidłowych FormGroup lub FormArray ... tylko nieprawidłowe FormControl's. Popełniłem ten sam błąd ... zobacz moją odpowiedź.
— Jette,

Poprawiłem moją odpowiedź, aby pasowała do twojego przypadku użycia.
— Karl Johan Vallner,

0

możesz rejestrować wartość formularza console.log(this.addCustomerForm.value), będzie konsolidować wszystkie wartości kontrolki, a następnie pola „” (puste) wskazują nieprawidłowe kontrolki

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.