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.