How to deal with form complexity in angular?

Pavlo Zhmak
3 min readAug 28, 2021

Form is not always a trivial issue and can became complex over time. We will try to look into that topic and try to answer the next questions:

· How to improve maintainability?

· How to improve conditional validation logic?

· How to improve testing of complex form?

That’s the repository where you can find source code of the sample from this article.

How to improve maintainability?

To achieve that we need to follow a few simple steps:

  • Decouple and organize the form into form groups and pass them as a parameter to child components.
  • Use observable value instead of form group value.
  • Use getter to access form group or it’s value from template.

There three ways how you can pass FormGroup to component: @Input(),ControlContainer, ControlValueAnccessor.

@Input() solve most of the use cases, but if you have some exceptional case then you can check another two options.

Note: I’ve notice that some people like to use ControlValueAnccessor to extract/isolate form group inside component. That’s sounds great, but in practice it’s difficult to follow when you keep form group away from parent component and you need to implement methods of interface even if you don’t need them.

There’s a nice way how you can use observable form value in angular:

The defer operator will create an observable only when we subscribe for it. By doing so we don’t need to care about subscription and you can place extra logic in tap.

How to improve conditional validation logic?

In my case we implemented conditional validation via subscribe on value changes. At the beginning everything was fine, but with time it grow into something hardly manageable.

To avoid that we need to keep in mind next few ideas that might sounds simple:

  • Minimize complex conditional and nested logic.
  • Subscribe on particular group/control when it’s possible.
  • Combine multiple form group value changes instead of keeping logic inside single form subscription.

In case you have a lot of conditional validation it will be useful to create something like this:

I don’t say that conditional validation helper should look like this, but you can use it as a hint. The example that I’ve mentioned at the beginning contains different version because it seems as overkill to use it here.

How to improve testing of complex form?

Spectatoris amazing tool that helps you to get rid of boilerplate code.

I’ll show you some example:

Let’s have a look at first test case where we implement the following steps:

  • Click on submit button: spectator.click(byText(‘Submit’))
  • Find the result element by test id: spectator.query(byTestId(‘result’))
  • Check it’s text content: expect(…).toHaveText(…)

With spectator it’s much more easy to work with plain DOM elements. Also there are extra matchers that comes with spectator out of the box (like: toHaveTextortoHaveAttribute).

As you can see it’s quite straightforward and easy to setup. Just give it a try and I’m pretty sure that you’ll like it.

P.S. In case you have some ideas or disagree with something will be glad to see your thoughts in comments.

--

--