user3353167
user3353167

Reputation: 892

Angular forms: best practise for complex nested reactive forms and validation at root component

I've been struggling for a few days to find a good pattern for my use case. I have a very complex reactive form, full of nested components, some fields are required, some fields may appear given certain conditions, etc... and this is creating a huge problem maintaining the code. The approach I used so far it passing the formControl to the children components and populate from there, but things started getting really hard to debug given the size of the form. A must for this form is that on submit of the whole form, a validation of all the nested fields is performed, and markAsTouched any field that is required but hasn't been inserted. I have been exploring 2 approaches but none of the 2 seems to be of any help:

I wonder if anyone has any experience with such forms and able to provide some guidance on what are the best practises in this case. I have made a very simple stackblitz with just one sub child using Control Container, unfortunately I wasn't able to make it run https://stackblitz.com/edit/angular-ivy-axbgr5

Upvotes: 13

Views: 6516

Answers (2)

Karol T
Karol T

Reputation: 1126

Complex forms in Angular can be a big trouble. From my experience the best approach is to create a stateful parent component and many children stateless components.

Parent component needs to be dedicated for particular form. Child components can be reused everywhere many times.

Parent component rules:

  • stateful
  • creates and holds form definition
  • emits form state (value, valid, pristine) on every form change
  • holds custom validation logic

Children components rules:

  • stateless
  • receives form parts (nested FormGroups) from parent
  • no custom validation logic

In above scenario children components are "reusable views" without any validation logic. It will always comes from parent.

How to pass form parts to children components`?

You can pass nested FormGroups in following ways:

ControlValueAccessor

In my opinion using ControlValueAccessor for creating form parts is not a good idea. Validation logic is encapsulated inside. It is good approach for create some really hard parts like a "color picker" but not just a "customer address" with several fields.

Business logic out of component

I have also tried to move business logic out of component with following simple code:

constructor(public businessLogic: VendorBusinessLogicService) { }

ngOnInit() {
    this.form = this.businessLogic.createForm(this.initialValue);

    this.subscription = this.form.valueChanges.subscribe(value => {
        this.businessLogic.applyBusinessLogic(value);
        this.emitFormState();
    });

    this.emitFormState();
}

Of course the requirement is to hold form reference inside the service. To be honest I cannot see benefits of it. This service for business logic looks scary. (https://github.com/p-programowanie/angular-forms/tree/forms-separated-business-logic)

Upvotes: 16

IAfanasov
IAfanasov

Reputation: 4993

I found it is best to create one dedicated service with all the form logic and structure. All the validations, dependencies, subscriptions, filling in the form groups and array are there. This way it is really easy to test the form parts and reuse them.

Upvotes: 2

Related Questions