Angular: Bad Practices/Patterns: Not Using Form Controls

Ryan Mackey-Paulsen
3 min readJan 28, 2020

--

Form Controls in Angular are one of those things that can save you from reinventing the wheel time and again if you use them correctly. You get so much out of the box with them that not using them can be a huge mistake. I get it though, do you use ReactiveFormsModule or FormsModule? What’s the difference? And maybe you’re building something quick and dirty and just need a working template with some inputs. Let’s dig into some examples and I’ll explain why it is always the best path to use form controls.

The ‘No Form’ Form

In a hurry to build a template and you haven’t made up your mind on template driven or reactive forms, you build something like this,

<select (change)="onChange($event.target.value)">
<option value='1'>First</option>
<option value='2'>Second</option>
<option value='3'>Third</option>
</select>

Yeah, this will get you somewhere fast, but you will completely miss out on some real benefits. For starters, form controls can give you those nice validation classes that you can use in your css. Maybe in the above example, the value is required, but nothing is selected when this is first rendered. How do you inform the user of this?

The above example also misses the mark on validation in general. If this was part of a form, either reactive or template driven, the value and the whole form can be checked for the validation status which is updated whenever the value changes, all done for you. With the approach in the example, we have to run our own validation, either in the onChange method or call a validation function from it, and manually update some field or property to tell us that it is not valid. Again, this is handled for you with the forms modules.

Use Custom Inputs

The next example is kind of the next step of form building. Let’s say you have a specific type of input that isn’t a native HTML input type. Don’t worry, because you can make your own form controls, AND YOU SHOULD! Here is what I have seen,

<search-input [query]="query" (onSelect)="update($event)"></search-input>

As mentioned in the previous example, this needs to be validated manually and will not include data changes and stream events with your ngModel. Yeah, combining this with ngModel is not great because now you have to keep track of changes from this input as well as your model.

On the surface, this input also gets passed the query, but if it contains a text input, this search component should keep that isolated and only emit value changes. Anyways…

Why not make it a form control? By implementing ControlValueAccessor you can make your own inputs that can be used with ngModel or formControl. With that, you will get the ability to validate with the form builder or ngModel directives and any changes will propagate to the parent Form!

If this search input was built using ControlValueAccessor, then its use would look something like this,

<search-input [(ngModel)]="selected" required></search-input>//or<search-input [formControl]="selected"></search-input>

And doesn’t that look like every other native form input in Angular?

So Don’t Do It

One of the things that Angular is really good at is building forms. And the developers of the framework knew that there would be inputs that needed to bind to data that HTML just didn’t support. If you even look under the hood, the ‘native’ inputs actually have built-in Angular directives that let you handle the change events and values within Angular. So, it makes sense that you can use those or build your own to make complex inputs that tap into the validation methods that are already given to you.

I’m pretty sure everyone has heard the expression, ‘don’t reinvent the wheel.’ This is one of those times where when you see an input that clearly is an input, but not being implemented as a form control, you should take the time to get your form building on the same page, keep your inputs consistent, and reap the benefits of Angular form controls in all of their glory.

--

--

Ryan Mackey-Paulsen

Web App Developer, Web Component Enthusiast, Musician, Human