Angular: Bad Practices

Armen Vardanyan
codeburst
Published in
8 min readJul 2, 2017

Angular is awesome. It provides hell of a lot functionality out of the box (routing, animations, HTTP module, forms/validations and etc), speeds up the development process and is really not that hard to learn and embrace (especially with such a powerful tool as Angular CLI).

But as always, a good instrument in incautious hands is a weapon of destruction, and today I am going to talk about some ways and practices in Angular which you definitely should NOT use. So, let’s get started.

Warning: I am going to provide examples of components in this article, and I will be using inline templates. Notice that this is, in most cases, A BAD practice, but is more comfortable for the readers to perceive.
Also, I will omit import statements and some boilerplate for the sake of brevity

Not making a REAL use of Angular’s components

Components are the essential building blocks in an Angular ecosystem, the bridge which connects our application’s logic with the view. But sometimes developers strongly overlook the benefits that a component provides. Consider this example:

As you can see, we have a little form with three controls, and a template which contains the actual inputs. Each input is put inside a div element, alongside with its label, and the three containers repeat themselves. They are essentially the same, so, maybe, separate them into a component? Now take a look at this:

If we have to change anything which concerns every form control in our app, we will just change it here, problem solved

So, we have separated a single control to it’s own component, and we have defined inputs to pass data from the parent component, in this case, the form control instance and the label of the input. Let’s revise our first component’s template:

Much neater

This one was a very simple example, but stuff like this may become very complex, if components are not used correctly. Say, you have a page which incorporates an article feed, an infinitely scrollable block, separated by topics, with smaller blocks representing individual news/articles (just like Medium. In fact, here is an explanation based on Medium’s article feed itself).

Perfect example of how Angular components can be used

Now, if we are up to creating something like this, we may wonder, how to use components to make our lives easier. Here’s how we should:

Decomposing a Medium article feed into Angular components

Now, the larger piece would be a component (marked with red). This will contain a list of featured articles, a follow/unfollow functionality, and a title of the topic. Smaller pieces would be components too (marked with green). They will, in their turn, contain an object with a single article’s info,bookmark story/report story functionality and a link to the entire article itself. See how this helped to separate most of the logic (divide and conquer!) into reusable pieces of code, which will be more manageable later, if any changes needed.

You may think “well, separating components is a simple Angular concept, why would you mention this as something so important, everyone knows this”, but the problem is that many developers are deceived by Angular’s router module: it maps a route to a component, and so people (mostly newbies, but sometimes it happens with more experienced devs too) start to think of these components as of separate pages. Angular component is NOT a page, it is a piece of the view, and several components together compose a view. Another nasty situation is when you have a small component, mostly without any specific logic, but it just grows larger and larger as new requirements arrive, and, at one point of time, you should start thinking of separation, or you may end up with an uncontrollable, ugly monstrosity of a component.

Using .toPromise()

Angular comes with it’s own out-of-the-box HTTP module for our app to talk to a remote server. As you should already know (otherwise: why are you reading this article?) that Angular uses Rx.js to support HTTP requests, instead of Promises. You know what? Not everyone knows Rx.js, but if you are going to use Angular for a long term project, you definitely should learn it. Those who are new to Angular tend to just transform Observables, which are returned from API calls in the HTTP module, to Promises, using .toPromise(), just because they are familiar with it. Well, that’s probably the worst thing you can do to your application, because just for the sake of your laziness you:

  1. Add unnecessary logic to your app. You don’t need to transform an Observable to a Promise, you can work with the stream of data itself
  2. Lose lots of awesome stuff that Rx.js provides: you could cache a response, you could manipulate the data before subscribing to it, you could find logical mistakes in the received data (e.g. if your API always returns 200 OK with a ‘success’ boolean property to determine whether things went on well) and rethrow errors to catch them later on in your app with just one or two lines of code… but you preferred .toPromise() instead.

Not using Rx.js more often

This one is more of a general advice. Rx.js is awesome, and you should consider using it to manipulate your data, events and your application’s overall state with it.

The forgotten directives

And this one’s old. Angular does not use directives as much as Angular.js did (we had lot’s of stuff like ng-click, ng-src, most of them now replaced with Inputs and Outputs), but it still has some: ngIf, ngForOf. The rule of thumb for Angular.js was

Do not do DOM manipulations in a controller

The rule for thumb for Angular should be:

Do not do DOM manipulations in a component

It’s all you need to know. Do not forget about the directives.

Not having interfaces defined for your data

Sometimes you may tend to think about the data retrieved from a server/API as any data, that’s it, type any. That’s not really the case. You should define all the types for every data you receive from your backend, because, you know, after all, that’s why Angular choose to be used mainly on TypeScript.

Doing data manipulations in a component

This one’s tricky. I suggest not to do that in a service either. Services are for API calls, sharing data between components and other utilities. The data manipulations instead should belong to separate model classes. Take a look at this:

When working with a server, you will most certainly find yourself in situations, where you have to change the way your data is represented

Now, this does not look like a catastrophe, just a little data manipulation before sending the values to backend. But imagine if there are lots of Foreign Keys, Many-To-Many fields, lots of data handling, depending on some cases, variables, your app’s state… Your onSubmit method may quickly become a mess. Now consider doing this:

Now, as you see, we have a class, representing a user, with all the manipulations inside it’s constructor. The component will now look like this:

And any further data manipulations will go inside the model constructor, thus not polluting the component’s code. As another rule of thumb , you may look to have a new keyword before each time sending data to a server.

Not using/Misusing Pipes

I want to explain this one with an example rightaway. Say you have two dropdowns which allow to select a weight measurement unit. One represents a measurement as is, the other is a measurement per some price/quantity (this is an important detail). You want the first to be presented as is, but as for the second, you want the labels to be preceded with a slash ‘/’, so it looks like ‘1 dollar / kg’ or ‘7 dollars / oz’. Have a look at this:

So, we see that both dropdown components use the same array of options, so they will look similar. Now we have to separate them somehow.

Stupid way:

This, of course, solves the problem, but what if the values are not just constant values stored inside the components, but, for example, are retrieved from a server? And, of course, creating a new property for every single data mutation will soon see us in a mess.

Dangerous way:

This may look like good solution, but in reality, this is even worse. The dropdown will render and look fine, until you try to click on it, and maybe even before that you may notice that it is blinking (yes, blinking!). Why? To understand that, you may need to dive a little into how inputs and outputs work with Angular’s change detection mechanism.

The dropdown component has an options input, and will re-render the dropdown every time that the input’s value changed. Here, the value is determined after a function call, so the change detection mechanism has no way to determine whether it has changed or not, so it will just have to constantly call the function on each change detection iteration, and the dropdown will be constantly re-rendered. Thus, the problem is solved… by creating a bigger problem.

Fine way:

Well, you are of course familiar with the pipes. This is still not a very specific advice (well, the documentation itself tells us to use them in such cases), but the real point I want to make is not the pipes themselves. The point is: I don’t like this solution either. If I have lots of simple, but different data mutations in my app, should I write a Pipe class for each and every one of them? What if most of them are so specific that are only used in one and only one context of a component? This looks like a huge amount of clutter.

A more advanced solution:

What’s the difference? Well a pipe calls its transform method when and only when the data changes. As long as weightUnits do not change, the pipe will be invoked just one time instead of on every change detection iteration.

I don’t state you must have just one or two mapping Pipes and nothing else, but you should have more custom pipes on more complex stuff (working with datetime, etc) and where reuse is crucial, and for more component-specific manipulations you may consider having a universal pipe.

Note: if you pass a function to some kind of a universal pipe, make sure that this function is pure, that is without side-effects and independent from your components state. Rule of thumb: if you have a this keyword in such a method, it won’t work!
You may read more about pure functions in this article.

General notes on reusability

Whenever you write a component which can be reused by other developers, consider consistent checkings of everything that your component requires. If your component has an input of type T, which is required to be defined for the component to work properly, just check that this input’s value is actually defined in the constructor. The input can be of type T, but it may be undefined at run-time as well (TypeScript provides only compile-time type checkings). Throw exceptions so that the actual error is exposed in a better context with your own custom message, rather than in some Zone.js context (as often happens with Angular errors).

Overall, be consistent and observant. You may find lot’s of unnecessary stuff in your app.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Published in codeburst

Bursts of code to power through your day. Web Development articles, tutorials, and news.

Written by Armen Vardanyan

Senior Angular developer from Yerevan, Armenia

Responses (16)

What are your thoughts?