각도 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-무효"클래스가
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()반환합니까?
Max Koretskyi

1
아무것도 반환하지 않으며 유효하지 않은 것은 비어 있습니다. 디버그 감시 화면에서 하나씩 확인했는데 모든 컨트롤이 유효하지만 this.AddCustomerForm.valid는 여전히 false를 반환합니다.
sa_ jul.

알아 낸 것 같아요. 이메일 필드와 정규식이 있지만 어떻게 든 컨트롤의 상태가 PENDING이고 원인 일 수 있습니다.
sa_

6
@ AngularInDepth.com - 컨트롤의 한 양식 그룹 인 경우, 함수는 잘못된 형태의 그룹이 아니라 잘못된 특정 양식 제어 돌아갑니다
존 스미스

35

방금이 문제에 맞서 싸웠습니다. 모든 양식 필드는 유효하지만 양식 자체는 여전히 유효하지 않습니다.

컨트롤이 동적으로 추가 / 제거되는 FormArray에 'Validator.required'를 설정 한 것으로 나타났습니다. 따라서 FormArray가 비어 있어도 여전히 필요했기 때문에 보이는 모든 컨트롤이 올바르게 채워져 있어도 양식은 항상 유효하지 않았습니다.

내 'findInvalidControls'함수는 FormGroup / FormArray가 아닌 FormControl 만 확인했기 때문에 양식의 잘못된 부분을 찾지 못했습니다. 그래서 나는 그것을 약간 업데이트했습니다.

/* 
   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
매우 유용한 답변입니다. 정말 고마워요
Mikki

1
매우 유용한 답변에 동의합니다.
nenea

20

Chrome의 DevTools에서 Console 탭을 선택합니다.

콘솔 프롬프트에서 명령을 입력하십시오.

document.getElementsByClassName('ng-invalid')

출력은 다음과 유사해야합니다. 여기에 이미지 설명 입력

이 경우 밑줄이 그어진 텍스트는 양식 컨트롤 용 listen-address입니다. 그리고 둘러싸인 텍스트 : .ng-invalid컨트롤이 유효하지 않음을 나타냅니다.

참고 : 크롬에서 테스트


2
나에게 이것은 질문에 답하는 가장 직접적인 방법 인 것 같습니다.
ckapilla

2
내가 당신에게 술을 사줄 수만 있다면 당신은 나를 미쳐가는 것으로부터 구했습니다
Adam Winnipass

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

1
빈 컨트롤이 있어도 null을 반환합니다.
sa_

1
오류가 없으면 null을 반환해야합니다. 템플릿을 게시 할 수 있습니까?
LookForAngular

예, 이것은 작동하지 않습니다. 각 양식 컨트롤에 설정된 다른 유효성 검사, 각 양식 컨트롤에는 오류가 포함되어 있지만 양식에는 없습니다. Maximus가 답변을 제공 한 것과 같은 컨트롤을 반복해야합니다.
AJT82

. 나는 this.form.controls [ '이메일'] 오류와 같은 각각의 contorls에 대한 오류에 액세스 할 수 있습니다
Nazrul Muhaimin

@ AJT_82 실제로 formGroup에 대해 유효성 검사기가 설정된 경우 Form 자체에 오류가 표시 될 수 있습니다 (컨트롤이 아닌 그룹에서 유효성을 검사하는 것이 합리적 인 교차 필드 유효성 검사에 대한 문서를 확인하십시오)
LookForAngular

3

이제 각도 9에서 markAllAsTouched () 메서드를 사용하여 잘못된 컨트롤 유효성 검사기를 표시 할 수 있습니다.

this.AddCustomerForm.markAllAsTouched();

내가 알아야 할 것을 알아내는 데 도움이 되었기 때문에 +1을 주려고합니다. 사용자가 입력을 반드시 터치하지 않았을 때 유효성 검사 메시지를 표시하는 것입니다.
Sean Halls

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을 반환합니다.

FormControl 검사와 잘못된 배열 기능에 대한 추가를 별도의 함수로 분리하는 경우 "instanceof"유형 검사 중 일부를 훑어 볼 수 있습니다. 이렇게하면 함수가 훨씬 깔끔해 보이지만 모든 잘못된 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

귀하의 사용 사례에 맞게 답변을 개선했습니다.
Karl Johan Vallner

0

형식의 값을 기록 할 수 있습니다. console.log(this.addCustomerForm.value)모든 컨트롤의 값을 콘솔 화 한 다음 null 또는 ""(빈) 필드는 잘못된 컨트롤을 나타냅니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.