Angular: Bad Practices/Patterns: Non-Generic Form Controls

Ryan Mackey-Paulsen
4 min readFeb 6, 2020

--

Generic enough to not know where it came from

I admit I struggled with the title for this one, but I’m talking about creating a select/multi-select input for every type of data you want to be selectable. This comes from a fear of making things to abstract and not being able to picture a common set of reusable components that make up your inputs.

The real struggle comes when you see the input as the way to get and set a specific field. Let’s say that field is an enum of colors: strings (‘#eee’, ‘#fff’, …). If the list of colors is coming from an API then you end up building that API call into your color input. It could be using a service or in the component, it doesn’t matter right now.

Now, you see another input field that is an enum of foods: also strings. You build a new food input that also needs to make an API call to get a list of foods from the server and you call it a day. Now you have something like this:

<color-input [(ngModel)]="color"></color-input>
<food-input [(ngModel)]="food"></food-input>

The Problem

After looking at the inputs for a while, you come to realize that they look very similar. Let’s say they are custom made dropdown selections and have special styles so you couldn’t just make these select inputs. OK, so what is the issues here? Think about what a dropdown/select input actually is. It is a box that, when is gains focus, shows a list that can be scrolled and the list items can be selected. Thinking about this, you should realize that you didn’t need two separate components, but one that takes the options and builds the list out of them.

Think about this, too. If you used the native select input, are there different versions of that element based on where the data is coming from? Instead, if we were to update the input to take, say, an observable, we could have a single input for both food and colors by giving it the http request to the api and having the options build the list on the response. The end result from above would look like:

<custom-input [options]="$colors" [(ngModel)]="color"></custom-input>
<custom-input [options]="$foods" [(ngModel)]="food"></custom-input>

The benefit here is that now we only have one component and where the data comes from doesn’t matter, this component just shows the options given to it. If there are specific transformations you need to do to get the options to work based on the API response, just add a map to the pipe of the observable from the API request. Again, the input just need to show the options and shouldn’t know or care about where they came from or what the object structure looked like before they were turned into options.

Why Would You See This

Again, most likely, this is from someone who is not familiar with abstract or ‘dumb’ components. That is fine for developers starting out with web development, but more experienced Angular developers should see this as an opportunity to combine components and introduce more reusability. Based on the example above, I have seen other inputs that can use the same dropdown list. An autocomplete text input, multi-select, a sub-menu…

It is this reusability where web components and Angular components really shine. Being able to break down UI into small, isolated pieces that are generic means you don’t have to reinvent the wheel everywhere you see that same UI. How abstract you get can be debatable, but it shouldn’t stop you from making things reusable and it shouldn’t force you into making the same components multiple times.

So Don’t Do It

Reusability is one of those things that can save you time and money. Remember, your development time costs someone money (you or your employer). Sure you can copy and paste a lot of boiler plate code and call it a day, but how do you debug and fix issues when you have your code and html templates copied in several places? If you fix something, are you sure you applied that fix everywhere? How do you deploy that if you built a library of components and other projects depend on them?

Abstract and generic should not be looked down on in UI building. We are used to looking at the same thing in different contexts, we just don’t realize it or think too much about it. But, being able to visually see that UI components share commonalities and making them work in any number of contexts can be a tricky thing. Taking the time to do it, though, can lead to big benefits and shrink the number of custom components you need. If not do it for that, do it for the time saved debugging.

--

--

Ryan Mackey-Paulsen

Web App Developer, Web Component Enthusiast, Musician, Human