Clean Up Your Angular Form Template

Netanel Basal
Netanel Basal
Published in
3 min readJan 10, 2017

--

In my previous article, we talked about how to show form errors on submit.

When your form start to grow, you can end up with something like this:

If you are coding all your forms like that, you are probably Psychopath 😜 (just kidding)

The template is verbose; it’s hard to understand what’s going on and you are not DRY.

What if we could write something like this:

I think that looks a lot better ( later you will see how we can be even cleaner than that ). So let’s create the control-errors component.

We need two Inputs:

  1. The control name.
  2. The errors Object.

Next, we can ask Angular to give us the ngForm instance in our component via dependency injection with the Host decorator. ( we are using also the Optional decorator to protect our code )

That’s the equivalent of doing this in our template:

<form #myform="ngForm"></form>

If you are still confused from where this NgForm is coming, In a nutshell, it’s just a built-in directive with a selector that points to almost any form tag.

@Directive({
selector: ‘form:not([ngNoForm]):not([formGroup]),ngForm,[ngForm]’
})
export class NgForm extends ControlContainer implements Form {}

Ok, now we have the form instance let’s get the errors.

Our getter functionality is straight forward:

  1. Find the current control in our form instance.
  2. Loop over the Input errors keys.
  3. Check with the hasError() method if we have an error with the same key.
  4. Show the error.

That’s all! You can play with the plunker.

If you are happy with this implementation, you are done here. I’m still not happy. I think we can make it even cleaner, maybe something like this:

<control-errors control="firstName">

I’m not going to implement this fully, but I can give you a hint.

First, we need to centralize our errors object, so let’s do that with DI.

Now we can inject the CONTROL_ERRORS object and implement more complex logic. It will take more time, but the benefits are obvious.

Currently, the control-errors directive works only with template driven forms. You need to add just a little bit of code to make it also work with reactive forms. You can check my plunker to see what are the changes.

👂🏻 Last but Not Least, Have you Heard of Akita?

Akita is a state management pattern that we’ve developed here in Datorama. It’s been successfully used in a big data production environment for over seven months, and we’re continually adding features to it.

Akita encourages simplicity. It saves you the hassle of creating boilerplate code and offers powerful tools with a moderate learning curve, suitable for both experienced and inexperienced developers alike.

I highly recommend checking it out.

Follow me on Medium or Twitter to read more about Angular, Akita and JS!

--

--

A FrontEnd Tech Lead, blogger, and open source maintainer. The founder of ngneat, husband and father.