如何根据其他 Formfields 更改 Formfields 上的验证?

How to change validation on a Formfield depending on other Formfields?

目标是实现一个表单,仅当填写了一个或多个输入字段时才需要输入字段。如果 none 个字段已填写,则不需要任何字段。有人在网站上建议我应该使用“valueChanges”在字段上创建一个监听器,然后在监听器中实现逻辑。然后在侦听器内部的逻辑之后,我调用方法“updateValueAndValidity()”。 现在这里出现问题。如果我包含“updateValueAndValidity()”,我会收到错误消息: Recursion Error in the Browser。我真的不明白为什么我在这个问题上会出现递归错误,因为我看不到递归在哪里。可能“updateValueAndValidity()”再次触发了我的监听器。

如果我不包含“updateValueAndValidity()”,我不会收到递归错误,但逻辑不起作用。我不知道如何解决这个问题,有人可以帮助我吗?

isFormEmtpy: boolean = true;
lieferadresseForm: FormGroup;
   
onChanges() {
        let street = this.lieferadresseForm.get('street');
        let streetNumber = this.lieferadresseForm.get('streetNumber');
        let zipCode = this.lieferadresseForm.get('zipCode');
    
        this.lieferadresseForm.valueChanges.subscribe(val => {
          console.log(val);
          this.isFormEmtpy = true;
          if(val.street !== '') {
            this.isFormEmtpy = false;
          } else if(val.streetNumber !== '') {
            this.isFormEmtpy = false;
          } else if(val.zipCode !== '') {
            this.isFormEmtpy = false;
          }
    
          if(this.isFormEmtpy == false) {
            street.setValidators([Validators.required, Validators.maxLength(36)]);
            streetNumber.setValidators([Validators.required, Validators.maxLength(10)]);
            zipCode.setValidators([Validators.required, Validators.maxLength(10)]);
          } else {
            street.setValidators([Validators.maxLength(36)]);
            streetNumber.setValidators([Validators.maxLength(10)]);
            zipCode.setValidators([Validators.maxLength(10)]);
          }

          strasse.updateValueAndValidity();
          hausnummer.updateValueAndValidity();
          postleitzahl.updateValueAndValidity();
            
        });
      }
    
      ngOnInit() {
        this.lieferadresseForm = this.formBuilder.group({
          street: ['', Validators.maxLength(36)],
          streetNumber: ['', Validators.maxLength(10)],
          zipCode: ['', Validators.maxLength(10)]
        });
            
        this.onChanges();
    }

您需要在 formControl 上使用 updateValueAndValidity()

yourForm.controls['controlName'].updateValueAndValidity();

在你的情况下会像

lieferadresseForm.controls['streetNumber']..updateValueAndValidity();

您可以将 {emitEvent:false} 对象配置传递给 updateValueAndValidity 方法以停止触发 valueChanges observable。

试试这个:

onChanges() {
        let street = this.lieferadresseForm.get('street');
        let streetNumber = this.lieferadresseForm.get('streetNumber');
        let zipCode = this.lieferadresseForm.get('zipCode');
    
        this.lieferadresseForm.valueChanges.subscribe(val => {
          console.log(val);
          this.isFormEmtpy = true;
          if(val.street !== '') {
            this.isFormEmtpy = false;
          } else if(val.streetNumber !== '') {
            this.isFormEmtpy = false;
          } else if(val.zipCode !== '') {
            this.isFormEmtpy = false;
          }
    
          if(this.isFormEmtpy == false) {
            street.setValidators([Validators.required, Validators.maxLength(36)]);
            streetNumber.setValidators([Validators.required, Validators.maxLength(10)]);
            zipCode.setValidators([Validators.required, Validators.maxLength(10)]);
          } else {
            street.setValidators([Validators.maxLength(36)]);
            streetNumber.setValidators([Validators.maxLength(10)]);
            zipCode.setValidators([Validators.maxLength(10)]);
          }

          strasse.updateValueAndValidity({emitEvent:false});
          hausnummer.updateValueAndValidity({emitEvent:false});
          postleitzahl.updateValueAndValidity({emitEvent:false});
            
        });
      }

问题是您正在订阅表单值更改到 onChange function.Basically您正在订阅表单更改在每个更改检测周期创建新的订阅,这会导致巨大的内存泄漏。

将您编写的代码移到 ngOnInit 函数或至少一个只调用一次的函数中。

在这种情况下,您不需要处理 onChange 生命周期,因为您正在监听表单更改本身。

最好创建一个自定义的formGroup的formError。它比你想象的更简单:只需在你的组件中创建一个函数:

   requiredIfOneNotEmpty()
    {
       return (formGroup:FormGroup)=>{
          const oneFilled=formGroup.value.street || 
                  formGroup.value.streetNumber || 
                  formGroup.value.zipCode
          if (!oneFilled)
              return null
          const error={}
          if (!formGroup.value.street)
              error.requiredStreet='Street is required';
          if (!formGroup.value.streetNumber )
              error.requiredStreetNumber='Street number is required'
          if (!formGroup.value.zipCode)
              error.requiredZipCode:'Zip code is required'

          return error
       }
    }

然后您可以简单地创建表单

formGroup=new FormGroup({
     street:new FormControl(null,Validators.maxLength(36)),
     streetNumber:new FormControl(null,Validators.maxLength(10)),
     zipCode:new FormControl(null,Validators.maxLength(10));
},this.requiredIfOneNotEmpty())

你检查错误使用

<div *ngIf="formGroup.errors?.requiredStreet">Required Street</div>
<div *ngIf="formGroup.errors?.requiredStreetNumber">Required Street Number</div>
<div *ngIf="formGroup.errors?.requiredZipCode">Required Zip Code</div>