Как найти недопустимые элементы управления в реактивной форме angular 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, но все выглядит хорошо.

Я попытался найти, проверив свойство статуса в коллекции элементов управления. Но мне интересно, есть ли способ найти недопустимые и отобразить их пользователю?

sa_
источник
Если вы просто хотите отобразить поля с ошибкой, вы можете использовать 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 возвращает ложный
SA_
что findInvalidControls()вам возвращается?
Макс Корецкий
1
он ничего не возвращает, недопустимый пуст. Я проверил один за другим на экране просмотра отладки, все элементы управления действительны, но this.AddCustomerForm.valid по-прежнему возвращает false.
SA_
Думаю, я узнал. есть поле электронной почты и регулярное выражение , но как - то состояние элемента управления является ОЖИДАНИЕ , и это может быть причина
SA_
6
@ 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;
  }
Jette
источник
3
Невероятно полезный ответ. Большое спасибо
Микки
1
Согласитесь, очень полезный ответ.
nenea
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

В любом случае, используя аксессор элементов управления, вы можете перебирать все элементы formControl в вашей форме.

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
     })
LookForAngular
источник
1
это возвращает нуль даже есть свободные средства управления
SA_
1
Он должен возвращать значение null, если ошибок нет. Вы можете опубликовать свой шаблон?
LookForAngular
Да, это не сработает, разные проверки, установленные для каждого элемента управления формой, эти элементы управления каждой формы содержат свои ошибки, а форма - нет. Вам нужно перебрать элементы управления, как Максимус дал ответ.
AJT82
Я могу получить доступ к ошибкам для каждого отдельного элемента управления, например this.form.controls ['Email'].
Errors
@ AJT_82 действительно, сама форма может показывать ошибки, если для formGroup установлен валидатор (проверьте документы о проверке перекрестных полей, которая имеет смысл проверять в группе, а не в элементе управления)
LookForAngular
3

Теперь в angular 9 вы можете использовать метод markAllAsTouched () для отображения валидаторов недопустимых элементов управления:

this.AddCustomerForm.markAllAsTouched();
Родриго Хорхе Баптиста
источник
Собираюсь дать этому +1, так как это помогло мне узнать то, что мне нужно знать - а именно показать сообщения проверки, когда пользователь не обязательно касался входов.
Шон Холлс,
1

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

даршна мишра
источник
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. Просто введите formGroup верхнего уровня, и она вернет все недопустимые элементы FormControl.

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

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

Только для тех, кому это нужно, чтобы им не приходилось его кодировать самостоятельно.

Редактировать # 1

Было запрошено, чтобы он также возвращал недопустимые 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. Я совершил ту же ошибку ... см. Мой ответ.
Jette
Я улучшил свой ответ, чтобы он соответствовал вашему варианту использования.
Карл Йохан Валлнер
0

вы можете зарегистрировать значение формы console.log(this.addCustomerForm.value), оно будет консолью для всех значений элемента управления, тогда пустые поля или "" (пустые) поля указывают на недопустимые элементы управления

Сохаил Анвар
источник