Як знайти недопустимі елементи керування у кутовій 4 реактивній формі


89

У мене реактивна форма в Angular, як показано нижче:

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 повертає false, але все виглядає добре.

Я намагався знайти за допомогою перевірки властивості статусу в колекції елементів керування. Але цікаво, чи є спосіб знайти недійсні та показати їх користувачеві?


Ви просто хочете відобразити поля з помилкою, ви можете використовувати css, щоб виділити або розфарбувати недійсні поля. Кожне недійсне поле має у своєму списку класів клас "ng-invalid"
LookForAngular

Відповіді:


168

Ви можете просто переглядати кожен елемент керування та перевіряти статус:

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

1
дякую за це, але я спробував це, і навіть це нічого не повертає, моя форма все ще недійсна, це дивно. Я маю на увазі, що цей код виглядає добре, але не має сенсу, чому form.valid повертає false
sa_

що findInvalidControls()тобі повертає?
Макс Корецький,

1
він нічого не повертає, інвалід порожній. Я перевірив по черзі на екрані перегляду налагодження, всі елементи керування є дійсними, але this.AddCustomerForm.valid все ще повертає false.
sa_

Здається, я дізнався. є поле електронної пошти та регулярний вираз, але якимось чином елемент управління ВІДЧИСЛЮЄТЬСЯ, і це може бути причиною
sa_

7
@ AngularInDepth.com - якщо одним із елементів керування є група форм, ваша функція поверне недійсну групу форм, а не конкретний елемент керування формою, який є недійсним
Джон Сміт

35

Я щойно вирішив цю проблему: кожне поле форми є дійсним, але все-таки сама форма недійсна.

Виявляється, я встановив 'Validator.required' на FormArray, де елементи керування додаються / видаляються динамічно. Отже, навіть якщо FormArray був порожнім, він все одно був необхідним, а тому форма завжди була недійсною, навіть якщо кожен видимий елемент керування був правильно заповнений.

Я не знайшов недійсну частину форми, оскільки моя функція 'findInvalidControls' перевіряла лише FormControl, а не FormGroup / FormArray. Тож я трохи оновив:

/* 
   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
Неймовірно корисна відповідь. Щиро дякую
Міккі

1
Погодьтеся, дуже корисна відповідь.
ненея

20

У розділі DevTools у Chrome виберіть вкладку Консоль.

У командному рядку командного типу:

document.getElementsByClassName('ng-invalid')

Вихід повинен бути подібним до цього: введіть тут опис зображення

У цьому випадку підкреслений текст призначений для контролю форми listen-address. І обведений текст: .ng-invalidвказує на те, що елемент керування недійсний.

Примітка: Випробувано хромом


2
мені здається, це найпряміший спосіб відповісти на питання.
ckapilla

2
Ти врятував мене від божевілля, якби тільки я міг купити тобі напій
Адам Вінніпас

3

Як форми, так і всі елементи керування розширюють кутовий клас AbstractControl. Кожна реалізація має доступ до помилок перевірки.

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

Документи api містять усі посилання https://angular.io/api/forms/AbstractControl

Редагувати

Я думав, що програма доступу до помилок працювала таким чином, однак це посилання на github показує, що є деякі інші люди, які думали так само, як і я https://github.com/angular/angular/issues/11530

У будь-якому випадку, використовуючи доступ до елементів керування, ви можете переглядати всі formControls у вашій формі.

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
це повертає нуль, навіть якщо є порожні елементи керування
sa_

1
Він повинен повертати значення null, коли помилок немає. Чи можете ви опублікувати свій шаблон?
LookForAngular

Так, це не буде працювати, різні перевірки, встановлені в кожному елементі керування формою, ці елементи керування формою містять свої помилки, а форма ні. Вам потрібно повторити елементи управління, як Maximus дав відповідь.
AJT82,

Я можу отримати доступ до помилок для кожного окремого контролю, наприклад this.form.controls ['Електронна пошта']. Помилки
Nazrul Muhaimin

@ AJT_82 справді сама форма може показувати помилки, якщо для групи Group було встановлено валідатор (перевірте документи про перевірку перехресного поля, що має сенс перевірити в групі, а не в
елементі

3

Тепер, в кутовій 9, ви можете використовувати метод markAllAsTouched (), щоб показати недійсні валідатори елементів керування:

this.AddCustomerForm.markAllAsTouched();

Збираючись дати цьому +1, оскільки це допомогло мені з’ясувати, що мені потрібно було знати --- це показати повідомлення про перевірку, коли користувач необов’язково торкався входів.
Шон Холлс

1

Якщо у вас не так багато полів у формі, ви можете просто натиснути F12 і навести курсор на елемент керування, і ви зможете побачити спливаюче вікно із первинними / торкнутимися / дійсними значеннями поля - "# fieldname.form-control.ng- недоторканий.ng-недійсний ".


1

Я думаю, вам слід спробувати використовувати this.form.updateValueAndValidity()або спробувати виконати той самий метод у кожному з елементів керування.


1

спробуйте це

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

1

Буде записано всі імена елементів керування 😊

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

Ви можете створити з цього масив або рядок і показати користувачеві


0

Я дозволив собі вдосконалити код AngularInDepth.com -s, щоб він також рекурсивно шукав недійсні введення у вкладених формах. Чи буде він вкладений у FormArray-s або FormGroup-s. Просто введіть форму GroupGroup верхнього рівня, і вона поверне всі недійсні формиControls.

Ви можете скинути деякі перевірки типу "instanceof", якщо б ви розділили перевірку FormControl та додавання до недійсних функцій масиву в окрему функцію. Це зробило б функцію набагато чистішою, але мені потрібна була глобальна, одна функція, опція, щоб отримати плоский масив усіх недійсних формControls, і це рішення!

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

Тільки для тих, хто цього потребує, тому їм не потрібно кодувати це самостійно ..

Редагувати No1

Було запропоновано також повернути недійсні FormArray-s та FormGroups, тому, якщо вам це також потрібно, використовуйте цей код

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
Я спробував, але він не знаходить жодного недійсного FormGroup чи FormArray ... лише недійсні FormControl. Я зробив ту ж помилку ... див. Мою відповідь.
Джетт,

Я покращив свою відповідь відповідно до вашого варіанту використання.
Karl Johan Vallner

0

Ви можете реєструвати значення форми console.log(this.addCustomerForm.value), воно буде консолірувати всі значення елемента керування, тоді значення null або "" (порожні) означатимуть недійсні елементи керування

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.