代码之家  ›  专栏  ›  技术社区  ›  Ankit Bhardwaj

Angular Form Group未清除条件验证器错误

  •  1
  • Ankit Bhardwaj  · 技术社区  · 7 月前

    我有一个下拉菜单,根据所选选项,我显示特定的表单控件。对于下拉选项value2,我显示了一条错误消息:“请提供正文或用户名和密码”,表示需要其中一个字段才能保存表单。问题是,当我从下拉列表中选择选项value1或value3时,错误消息(h6)仍会出现在表单上,atLeastOne验证错误仍然存在。即使更改了下拉列表值,我也无法重置或清除此错误。

    模板代码:

        <form [formGroup]="form">
            <h2 style="display: inline-block;">{{action}} {{operationName}}</h2>
            <h6 style="color: red; display: inline-block;margin: 0;margin-left: 0.3rem;"
                *ngIf="isSaveDisabled()">
                (Required Field is/are missing)
            </h6>
            <h6 style="color: red; display: inline-block;margin: 0;margin-left: 0.3rem;"
                *ngIf="form.getError('atLeastOne') != null">
                (Please provide either the Auth Request Body or both Username and Password)
            </h6>
            <ng-container [ngSwitch]="column['type']">
                <!-- Text Input -->
                <!-- Dropdown Input -->
                <select *ngSwitchCase="'dropdown'" id="{{column['label']}}"
                        formControlName="{{column['label']}}"
                        (change)="handleDropdownChange(column['label'])">
                    <option value="">ALL</option>
                    <option *ngFor="let item of column['options']" [value]="item">
                        {{item}}
                    </option>
                </select>
            </ng-container>
        </form>
    

    ts文件:-

        ngOnInit() {
        this.columns = [
            {
                label: 'Type',
                value: '',
                type: 'dropdown',
                required: true,
                options: ['value1', 'value2', 'value3'],
            },
            {
                label: 'Body',
                value: '',
                type: 'inputTextArea',
                required: true,
            },
            {
                label: 'Username',
                value: '',
                type: 'inputTextField',
                required: true,
            },
            {
                label: 'Password',
                value: '',
                type: 'inputTextField',
                required: true,
            },
        ];
        this.columns?.forEach((column) => {
          const control = this.fb.control(
            column.value,
            column.required ? Validators.required : null
          );
          this.form.addControl(column.label, control);
        });
    
        if (value === 'value2') {
          console.log('this is called');
          this.form.get('Username')!.clearValidators();
          this.form.get('Password')!.clearValidators();
          this.form.get('Body')!.clearValidators();
          this.form.setValidators(this.conditionalValidator());
          this.form.updateValueAndValidity();
          this.cdr.detectChanges();
        }
        console.log('Form after adding controls: ', this.form.value);
      }
            }
    
        handleDropdownChange(value: string): void {
            console.log('Handling Option2 change:', value);
            console.log('Before:', JSON.stringify(this.form.errors, null, 2));
            console.log('1 ' + this.form.getError('required'));
            // Clear errors on each form control
            Object.keys(this.form.controls).forEach((key) => {
                const control = this.form.get(key);
                console.log('Control error:', control?.errors);
                if (control) {
                    control.setErrors(null);
                    control.updateValueAndValidity();
                }
            });
            console.log('2 ' + this.form.getError('required'));
            // On dropdown change we have to clear the errors
            console.log('1 ' + this.form.getError('atLeastOne'));
            this.form.setErrors({ atLeastOne: 'good' });
            this.form.updateValueAndValidity();
            console.log('2 ' + this.form.getError('atLeastOne'));
        
            this.form.get('atLeastOne')?.setErrors({
                atLeastOne: 'Atasdsd.',
            });
        
    
            this.form.updateValueAndValidity();
            this.cdr.detectChanges();
            this.clearRequiredValidators();
            // this.form.updateValueAndValidity();
            console.log('Form errors after:', JSON.stringify(this.form.errors, null, 2));
            this.populateForm(value);
        }
    
    
    conditionalValidator(): ValidatorFn {
        return (control: AbstractControl): ValidationErrors | null => {
          const body = control.get('Body');
          const username = control.get('Username');
          const password = control.get('Password');
          if (body && authRequestBody.value.length > 0) {
            return null;
          }
          if (
            username &&
            password &&
            username.value.length > 0 &&
            password.value.length > 0
          ) {
            return null; 
          }
          return { atLeastOne: 'At least one field has to be provided.' }; 
        };
      }
    

    控制台打印:-

    Before: {
      "atLeastOne": "At least one field has to be provided."
    }
    consumer-details.component.ts:418 1 undefined
    consumer-details.component.ts:422 Control error: null
    consumer-details.component.ts:422 Control error: null
    consumer-details.component.ts:422 Control error: null
    consumer-details.component.ts:422 Control error: null
    consumer-details.component.ts:422 Control error: null
    consumer-details.component.ts:422 Control error: null
    consumer-details.component.ts:422 Control error: null
    consumer-details.component.ts:422 Control error: {required: true}
    consumer-details.component.ts:422 Control error: null
    consumer-details.component.ts:422 Control error: null
    consumer-details.component.ts:422 Control error: null
    consumer-details.component.ts:432 2 undefined
    consumer-details.component.ts:434 1 At least one field has to be provided.
    consumer-details.component.ts:437 2 At least one field has to be provided.
    consumer-details.component.ts:446 Form errors afte: {
      "atLeastOne": "At least one field has to be provided."
    }
    

    即使在更改下拉值后,h6消息也会显示出来。我正在使用自定义验证器功能

    1 回复  |  直到 7 月前
        1
  •  1
  •   sori    7 月前

    问题是你从不删除你的 conditionalValidator . 这意味着,无论下拉选择如何,验证器都会继续运行。

    一种解决方案是检查接收到的值是否等于 value2 或者不。如果相等,则设置验证器,否则将其删除( this.form.setValidators(null) )

    例如:

    handleDropdownChange(value: string): void {
      // Remove any existing form errors. (It might not be necessary in your case)
      this.form.setErrors(null);
    
      // If the user chose 'value2', apply your conditional validator
      if (value === 'value2') {
        this.form.setValidators(this.conditionalValidator());
      } else {
        // otherwise remove it
        this.form.setValidators(null);
      }
      
      // Re-validate
      this.form.updateValueAndValidity();
    
      // additional logic …
    
      this.cdr.detectChanges();
      this.populateForm(value);
    }
    
    推荐文章