多重验证在模板驱动表单中无法正常工作

问题描述 投票:0回答:1

我遇到多重验证无法正常工作的问题。 例如 validate1 方法检查输入是否为空,validation2 方法检查 name1 和 name2 值是否相等。例如 name1= Angular 且 name2 为空。形式有效是显示为真,但实际逻辑为假

validate1() - 设置表单有效 false,validate2() - 设置表单有效 true,根据逻辑形式无效

注:

  1. 有些场景我只会使用 validate1(),有些场景我会使用 仅 validate2(),某些场景我将同时使用两者

  2. validate1()、validate2() 是示例逻辑。我还需要方法3 通过方法2的验证器

    导入{ 成分, 指示, 关于变化, 初始化时, 转发参考, 输入, 注射器, 查看孩子, NG形式 来自“@Angular/Core”; 从 '@angular/platform-browser' 导入 { bootstrapApplication } ; 进口 { NG_VALIDATORS, 验证器Fn, 抽象控制, 验证错误, NG控制, 反应式表单模块, 表单模块, 表单控件, 来自“@角度/形式”; 从 '@angular/common' 导入 { CommonModule };

    @Directive({
      selector: '[appdirective1]',
      standalone: true,
    })
    export class directiveName implements OnChanges, OnInit {
      @Input() varName1 = '';
      @Input() varName2 = '';
      @Input() callBack1!: (control: AbstractControl) => ValidationErrors | null;
      @Input() callBack2!: (control: AbstractControl) => ValidationErrors | null;
      constructor(private _injector: Injector) {}
    
      validate1(): ValidatorFn {
        return (control: AbstractControl): ValidationErrors | null => {
          //logic here it is sample logic
          return (control.value !== '' || control.value !== null || control.value !== undefined)
            ? {
                invalidName: control.value,
              }
            : null;
        };
      }
      validate2(): ValidatorFn {
        return (control: AbstractControl): ValidationErrors | null => {
          const obj1 = this.callBack1(control);
    
          return obj1;
        };
      }
      validate3(): ValidatorFn {
        return (control: AbstractControl): ValidationErrors | null => {
          const obj1 = this.callBack2(control);      
          return obj1;
        };
      }
      ngOnInit() {
        this.conditionallyAddValidators();
      }
    
      conditionallyAddValidators() {
        const control = this._injector.get(NgControl);
        control?.control?.addValidators(this.validate1());
        if (this.varName1 !== '' && this.varName1 !== undefined) {
          control?.control?.addValidators(this.validate2());
        }
        if (this.varName2 !== '' && this.varName2 !== undefined) {
          control?.control?.addValidators(this.validate3());
        }
        control?.control?.updateValueAndValidity();
      }
    
      ngOnChanges() {
        this.conditionallyAddValidators();
      }
    }
    
    @Component({
      selector: 'app-root',
      standalone: true,
      imports: [directiveName, ReactiveFormsModule, CommonModule, FormsModule],
      template: `
    <form #f="ngForm">
        <input appdirective1 name="name1" [callBack1]="method2" [formControl]="control" [(ngModel)]="name1"/>
        <br/>
    
        <br/>
        <hr/>
    <input appdirective1 name="name2"" [callBack2]="method1" [(ngModel)]="name2" />
        <br/>
       {{f.valid | json}}
        <br/>
        <hr/>
    </form>
      `,
    })
    export class App {
    
      name1 = 'Angular';
    name2="";
      success = 'required';
     @ViewChild('f', {static:false}) form:NgForm;
      method1(control: AbstractControl) {
        const value = control?.value;
        return this.form.form.get('name2').value !==this.form.form.get('name1').value
          ?null 
          : {
              minLength: true,
            };
      }
    
      method2(control: AbstractControl) {
        const value = control?.value;
        return value?.length >= 10
          ? {
              maxLength: true,
            }
          : null;
      }
    

    方法3(控制:AbstractControl){ //自己的逻辑 返回值?.length >= 10 ? { 最大长度:真, } : 无效的; } }

    bootstrapApplication(App);
    
angular angular-directive angular-forms angular-template-form
1个回答
0
投票

validate1
中:您有一个始终为 true 的条件,因为您错误地使用了
or
运算符:
return (control.value !== '' || control.value !== null || control.value !== undefined)

您正在尝试将

callBack1
callBack2
连接到
validate2
validate3
等验证器,但这样做背后的逻辑令人困惑,因为您单独提供
callBack1/callBack2
作为输入。

对于何时以及如何调用方法

method1
method2
存在一些困惑。

根据需要创建可重用的自定义验证器。 使用复合验证器有效地组合多个验证条件。 动态管理特定领域的验证者而不干扰其他领域。

重构指令代码

import {
  Directive,
  OnChanges,
  OnInit,
  Input,
  Injector,
  ChangeDetectorRef,
} from '@angular/core';
import {
  NG_VALIDATORS,
  ValidatorFn,
  AbstractControl,
  ValidationErrors,
  NgControl,
} from '@angular/forms';

@Directive({
  selector: '[appdirective1]',
  providers: [
    {
      provide: NG_VALIDATORS,
      useExisting: DirectiveName,
      multi: true,
    },
  ],
})
export class DirectiveName implements OnChanges, OnInit {
  @Input() varName1 = '';
  @Input() varName2 = '';
  @Input() callBack1!: (control: AbstractControl) => ValidationErrors | null;
  @Input() callBack2!: (control: AbstractControl) => ValidationErrors | null;

  private control!: NgControl;

  constructor(private _injector: Injector, private cdr: ChangeDetectorRef) {}

  ngOnInit() {
    this.control = this._injector.get(NgControl);
    this.conditionallyAddValidators();
  }

  ngOnChanges() {
    this.conditionallyAddValidators();
    this.control?.control?.updateValueAndValidity(); // Trigger validation when inputs change
  }

  validate1(): ValidatorFn {
    return (control: AbstractControl): ValidationErrors | null => {
      // Ensure the input is not empty
      return control.value == null || control.value.trim() === ''
        ? {
            invalidName: 'Field is required',
          }
        : null;
    };
  }

  validate2(): ValidatorFn {
    return (control: AbstractControl): ValidationErrors | null => {
      const result = this.callBack1 ? this.callBack1(control) : null;
      return result;
    };
  }

  validate3(): ValidatorFn {
    return (control: AbstractControl): ValidationErrors | null => {
      const result = this.callBack2 ? this.callBack2(control) : null;
      return result;
    };
  }

  conditionallyAddValidators() {
    const control = this.control?.control;

    if (!control) return;

    // Clear existing validators
    control.clearValidators();

    // Always add validate1
    control.addValidators(this.validate1());

    // Add validate2 and validate3 when conditions or callbacks are provided
    if (this.varName1 !== undefined && this.varName1 !== '') {
      control.addValidators(this.validate2());
    }
    if (this.varName2 !== undefined && this.varName2 !== '') {
      control.addValidators(this.validate3());
    }

    control.updateValueAndValidity(); // Make sure validator updates are reflected
  }
}

和下面的组件代码

import {
  Component,
  ViewChild,
} from '@angular/core';
import { FormControl, NgForm, ValidationErrors } from '@angular/forms';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [],
  template: `
    <form #f="ngForm">
      <!-- Field 1 -->
      <input
        appdirective1
        name="name1"
        [callBack1]="method2"
        [(ngModel)]="name1"
        varName1="used"
      />
      <br />

      <!-- Field 2 -->
      <input
        appdirective1
        name="name2"
        [callBack2]="method1"
        [(ngModel)]="name2"
        varName2="used"
      />
      <br />

      <hr />
      <!-- Valid State -->
      <div>Form Valid: {{ f.valid | json }}</div>
      <!-- Errors for Field 1 -->
      <div>
        Name1 Errors: {{ f.form.controls['name1']?.errors | json }}
      </div>
      <!-- Errors for Field 2 -->
      <div>
        Name2 Errors: {{ f.form.controls['name2']?.errors | json }}
      </div>
    </form>
  `,
})
export class App {
  name1 = 'Angular';
  name2 = '';

  @ViewChild('f', { static: false }) form!: NgForm;

  method1(control: AbstractControl): ValidationErrors | null {
    const name1Value = this.form?.form.get('name1')?.value;
    return control.value !== name1Value
      ? null
      : {
          valuesMatch: true, // error when name1 and name2 are equal
        };
  }

  method2(control: AbstractControl): ValidationErrors | null {
    return control.value && control.value.length >= 10
      ? {
          maxLength: true,
        }
      : null;
  }
}
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.