Reactive Form Always Valid, Even When Not. Nested Children in Form

谁说胖子不能爱 提交于 2020-07-10 10:27:00

问题


I have seen a few StackOverflow issues with this question, but none of them seem to have proven answers that work.

I am building a dynamically created Reactive Form Using Angular. StackBlitz here . The user has the option to add "groups" and "conditions" within the groups. Each group can be further nested using FormArrays.

The form works as expected. Here are the main pieces of the form:

  1. AppComponent: The main Parent Component
  2. GroupControlComponent: The child of the parent. Takes care of all the group objects
  3. ConditionFormComponent: The child of the GroupControlComponent. Takes care of all the conditions within the groups

This is what a basic object looks like:

{
  // appcomponent level
  "statement": {
    //groupcontrol level
    "groups": [
      {
        // conditionform level
        "conjunctor": null,
        "conditions": [
          {
            "variable": null
          }
        ],
        "groups": []
      }
    ]
  }
}

When I set up validation, I want everything to be required. So I went through the FormBuilder, on the parent and children components, and set Validators.required to true on all form controls.

this._fb.control({
  conjunctor: null,
  conditions: [[], Validators.required],
  groups: [[], Validators.required]
 })

(this is the case on all controls)

The problem is, the form now always is valid. Even when the form is not actually valid. Is it possible to check form validity while using nested child components?

Here is some more information about this specific form, if required:

Cannot Find Control with Path Using ngIf on Recursive Angular Form

Angular Deeply Nested Reactive Form: Cannot find control with path on nested FormArray


回答1:


Stackblitz demo

Basically you must implement the Validator (not Validators - plural) interface. It has one mandatory method:

validate(c: AbstractControl) => ValidationErrors;

The method validate should return null if the control is valid and any other object if it is invalid.

One more thing is that you must provide NG_VALIDATORS (now, using plural) in the same way you provided NG_VALUE_ACCESSOR.

In summary:

@Component({
  ...

  providers: [
    ...
    {
      provide: NG_VALIDATORS,
      useExisting: forwardRef(() => GroupControlComponent),
      multi: true
    }
  ]
})
export class GroupControlComponent implements Validator {
  ...

  // Notice that we don't need to use the c parameter passed to the method.
  // We are using the `_form` instance property to verify what we need
  validate(c: AbstractControl): ValidationErrors {
    return this._form.valid ? null : {errors: 'form is invalid'}; 
  }
  ...
}

You must do it to your GroupControlComponent and the ConditionFormComponent.

[UPDATE]: You also need to take care of the dynamically created controls. Inside group control, let's look at the one single component that has an input: the condition control. Instead of:

_addCondition() {
  this._conditionsFormArray.push(
    this._fb.control({variable: null})
  );
}

You should initialize the control with a validator that checks for the validity of variable because the underlying control associated with the variable attribute will only check this out after the user interacts with the input inside the ConditionFormComponent. So, you should write it like this:

_addCondition() {
  this._conditionsFormArray.push(
    this._fb.control({variable: null}, 
      (c: AbstractControl) => 
          c.value && c.value.variable ? null : {'required': true}
    )
  );
}

Where this is a validation function that checks for the validity of the variable attribute:

(c: AbstractControl) => 
    c.value && c.value.variable ? null : {'required': true}

If you don't do that, it'll override the validation in the underlying ConditionForm control (which states that the input is required). And you could have a weird state where the outer form (in GroupControl) is invalid, but the inner form (in the ConditionForm) is valid. As you're validating it on the outer form, you basically could even remove the Validators.required in the inner form and rely just on the outer form validation.



来源:https://stackoverflow.com/questions/62661972/reactive-form-always-valid-even-when-not-nested-children-in-form

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!