简体   繁体   English

单击按钮时不会触发 Angular FormGroup 自定义验证器

[英]Angular FormGroup custom validator not triggered on button click

I am using reactive forms Angular 4 and added a custom validator addressValidation to the form group - addressGroup.我正在使用反应式表单 Angular 4,并在表单组 - addressGroup 中添加了一个自定义验证器 addressValidation。 I am updating all fields to mark as touched on submit click.我正在更新所有字段以在提交点击时标记为已触摸。 Looks like the custom validator addressValidation doesn't trigger eventhough I marked all fields as touched.看起来自定义验证器 addressValidation 不会触发,即使我将所有字段都标记为已触摸。 I tried marking the formgroup (addressGroup) as touched and dirty on submit but no help.我尝试在提交时将表单组(addressGroup)标记为触摸和脏,但没有帮助。

In general what I am trying to achieve is - By default I want to make street number and Street name required.总的来说,我想要实现的是 - 默认情况下,我想让街道号码和街道名称成为必需。 If po box is entered then street number and Name is not required.如果输入邮政信箱,则不需要街道号码和姓名。 Apt # is only required only if street number and name is entered.仅当输入了街道号码和名称时才需要 Apt #。 I am trying to achieve this on the custom validator in the formGroup.我试图在 formGroup 中的自定义验证器上实现这一点。

Any idea on what I am doing wrong.关于我做错了什么的任何想法。 Any other alternate way to achieve the above requirement.实现上述要求的任何其他替代方法。 I am new to Angular and slowly learning the concepts.我是 Angular 的新手,正在慢慢学习这些概念。 Any suggestion on How to trigger the custom validator on submit.关于如何在提交时触发自定义验证器的任何建议。

     buildForm(): void {
            this.contactForm = this.fb.group({
                emailAddressControl: ['', [Validators.required, Validators.email, Validators.maxLength(100)]],
                phoneControl: ['', [Validators.required, Validators.minLength(10), Validators.maxLength(10)]],            
                addressGroup: this.fb.group({
                    streetNumber: ['', [Validators.maxLength(10)]],
                    pOBox: ['', [Validators.maxLength(8)]],
                    aptNumber: ['', [Validators.maxLength(8)]],
                    streetName: ['', [Validators.maxLength(60)]],
                    cityControl: ['', [Validators.required, Validators.maxLength(50)]],
                    stateControl: ['', [Validators.required, Validators.maxLength(2)]],
                    zipControl: ['', [Validators.required, Validators.maxLength(14)]],
                    countryControl: ['UNITED STATES OF AMERICA', [Validators.required]],
                }, { validator: addressValidation })
            })
            this.contactForm.valueChanges
                .debounceTime(800)
                .subscribe(data => this.onValueChanged(data));
            this.onValueChanged();
        }


    onSubmit(): void {


            this.markAllFormFieldsAsTouched(this.contactForm);
            this.onValueChanged();

    }

   private markAllFormFieldsAsTouched(formGroup: FormGroup) {
        Object.keys(formGroup.controls).forEach(field => {
            console.log(field);
            const control = formGroup.get(field);
            if (control instanceof FormControl) {
                control.markAsTouched({ onlySelf: true });
            }
            else if (control instanceof FormGroup) {
                this.markAllFormFieldsAsTouched(control);
                control.markAsTouched({ onlySelf: true });
            }
            else if (control instanceof FormArray) {
                for (let formgroupKey in control.controls) {
                    let formgroup = control.controls[formgroupKey];
                    if (formgroup instanceof FormGroup) {
                        this.markAllFormFieldsAsTouched(formgroup);
                    }
                }
            }

        });
    }

    function addressValidation(c: AbstractControl): { [key: string]: boolean } | null {
        if (c.pristine) {
            return null;
        }
        const pOBoxControl = c.get('pOBox');
        const streetNameControl = c.get('streetName');
        const streetNumberControl = c.get('streetNumber');
        const aptNumberControl = c.get('aptNumber');
        if (pOBoxControl.value === null || pOBoxControl.value === "") {
            if (streetNumberControl.value === null || streetNumberControl.value === "") {
                return { ['streetNumberRequired']: true, ['streetNameRequired']: true };
            }
            if (streetNameControl.value === null || streetNameControl.value === "") {
                return { 'streetNameRequired': true };
            }
        }
        else {
            if ((streetNameControl.value === null || streetNameControl.value === "")
                && (streetNameControl.value === null || streetNumberControl.value === "") && aptNumberControl.value !== "") {
                return { 'apartmentNumberInvalid': true };
            }
        }
    }

Template模板

 <div class="card">
            <div class="card-header bg-info text-white">
                <h2>Mailing Address:</h2>
            </div>
            <div formGroupName="addressGroup" class="card-body">
                <div class="row">
                    <div class="col-lg-4">
                        <div class="form-group">
                            <label class="form-control-label">PO Box:</label>
                            <input class="form-control"
                                   [ngClass]="displayFieldCss('pOBox')"
                                   type="text"
                                   formControlName="pOBox"
                                   placeholder=""
                                   maxlength="8" />
                            <span class="invalid-feedback" *ngIf="isValidToDisplayErrors('pOBox')">
                                {{validationMessage.pOBox}}
                            </span>
                        </div>
                    </div>
                    <div class="col-lg-4">
                        <div class="form-group">
                            <label class="form-control-label">Street Number:</label>
                            <input class="form-control"
                                   [ngClass]="displayFieldCss('streetNumber')"
                                   type="text"
                                   formControlName="streetNumber"
                                   placeholder=""
                                   maxlength="10" />
                            <span class="invalid-feedback" *ngIf="isValidToDisplayErrors('streetNumber')">
                                {{validationMessage.streetNumber}}
                            </span>
                        </div>
                    </div>
                    <div class="col-lg-4">
                        <div class="form-group">
                            <label class="form-control-label">Apt Number:</label>
                            <input class="form-control"
                                   [ngClass]="displayFieldCss('aptNumber')"
                                   type="text"
                                   formControlName="aptNumber"
                                   placeholder=""
                                   maxlength="8" />
                            <span class="invalid-feedback" *ngIf="isValidToDisplayErrors('aptNumber')">
                                {{validationMessage.aptNumber}}
                            </span>
                        </div>
                    </div>                    
                </div>
                <div class="row">
                    <div class="col-lg-12">
                        <div class="form-group">
                            <label class="form-control-label">Street Name:</label>
                            <input class="form-control"
                                   [ngClass]="displayFieldCss('streetName')"
                                   type="text"
                                   formControlName="streetName"
                                   placeholder=""
                                   maxlength="60" />
                            <span class="invalid-feedback" *ngIf="isValidToDisplayErrors('streetName')">
                                {{validationMessage.streetName}}
                            </span>
                        </div>
                    </div>
                </div>
                <div class="row">
                    <div class="col-lg-5">
                        <div class="form-group">
                            <label class="form-control-label">City:</label>
                            <input class="form-control"
                                   [ngClass]="displayFieldCss('cityControl')"
                                   type="text"
                                   formControlName="cityControl"
                                   placeholder="(required)"
                                   maxlength="50" />
                            <span class="invalid-feedback" *ngIf="isValidToDisplayErrors('cityControl')">
                                {{validationMessage.cityControl}}
                            </span>
                        </div>
                    </div>
                    <div class="col-lg-4">
                        <div class="form-group">
                            <label class="form-control-label">State/Province (Code):</label>
                            <input class="form-control"
                                   [ngClass]="displayFieldCss('stateControl')"
                                   type="text"
                                   formControlName="stateControl"
                                   placeholder="(required)"
                                   maxlength="3" />
                            <span class="invalid-feedback" *ngIf="isValidToDisplayErrors('stateControl')">
                                {{validationMessage.stateControl}}
                            </span>
                        </div>
                    </div>
                    <div class="col-lg-3">
                        <div class="form-group">
                            <label class="form-control-label">Zip:</label>
                            <input class="form-control"
                                   [ngClass]="displayFieldCss('zipControl')"
                                   type="text"
                                   formControlName="zipControl"
                                   placeholder="(required)"
                                   maxlength="14" />
                            <span class="invalid-feedback" *ngIf="isValidToDisplayErrors('zipControl')">
                                {{validationMessage.zipControl}}
                            </span>
                        </div>
                    </div>
                </div>
                <div class="row">
                    <div class="col-lg-12">
                        <div class="form-group">
                            <label class="form-control-label">Country:</label>
                            <input class="form-control"
                                   [ngClass]="displayFieldCss('countryControl')"
                                   type="text"
                                   formControlName="countryControl"
                                   placeholder="(required)"
                                   maxlength="50" />
                            <span class="invalid-feedback" *ngIf="isValidToDisplayErrors('countryControl')">
                                {{validationMessage.countryControl}}
                            </span>
                        </div>
                    </div>
                </div>
            </div>
        </div>

You must use control.updateValueAndValidity() like this您必须像这样使用 control.updateValueAndValidity()

onSubmit(): void {
 if (this.form.valid) {
 
 } else {
  this.validateAllFormFields(this.committeForm); 
  this.logValidationErrors(this.committeForm);
  this.scrollToError();
 }
}
validateAllFormFields(formGroup: FormGroup) {       
  Object.keys(formGroup.controls).forEach(field => {  
    const control = formGroup.get(field);             
    if (control instanceof FormControl) {             
      control.updateValueAndValidity()
    } else if (control instanceof FormGroup) {        
      this.validateAllFormFields(control);            
    }
  });
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM