“Learn from your mistakes” should be every developer's life mantra. But that doesn't mean that they should be all your mistakes, right? With a list including the most common Angular mistakes at hand, you'd get to narrow down the number of possible pitfalls that you risk falling into to the... uncommon, the less predictable ones.

So, what are the traps that Angular developers fall into most often as they build their applications?

We've run our own "investigations" for you:
 

  • gone through the code examples on the web
  • ran an inventory of the most frequent questions on StackOverflow
  • looked over some of the issues that we've knocked our heads against while working on our own Angular projects 
     

… and trimmed down our list to 5 most frequent mistakes that Angular developers make:


1. ngOnChanges vs ngDoCheck: Misunderstanding When the ngDoCheck Gets Triggered 

"I have used OnPush strategy for my component and no bindings have changed, but the ngDoChecklifecycle hook is still triggered. Is the strategy not working?"

I bet that you've stumbled across this question (maybe put into different words) on various developer forums. It could easily win any “popularity” test there since it keeps coming up again and again.

But, before we give it a straight answer and settle this matter for good, let's focus on these 2 “change detecting” lifecycle hooks in Angular. And see where the problem stems from:

As you well know it, AngularJs has the watch feature, which “alerts” you whenever a value changes. Angular, on the other hand, has replaced the watch and scop feature with component inputs as properties. Moreover, it has added the ngOnChanges lifecycle hook, as well.

And here's where things get “tricky” and risk to turn into the trap that many Angular developers fall into:

The OnChanges event doesn't emit if/when a deep field of the input property changes. Hence, the value of the input is the reference of the object.

How do you approach this problem? You have several methods at hand, in fact, but I'm going to focus on the most common one:

Using the ngDoCheck lifecycle hook once you run the change detection process!

Now here's the answer that I've promised, to the above-mentioned common developer question:

The onPush strategy for detecting changes in Angular does work: the hook is triggered by the design itself!  

Note: another ridiculously frequent mistake that developers make is to take "Angular" for "AngularJS"! Be better than that: the term "AngularJS" should be used only when you refer to the old Angular and to Angular 1, while Angular 2/2+ 4 and 5 is just... "Angular". Mind you don't delve deep into this confusion yourself, too!
 

2. Forgetting to Unsubscribe: One of the Most Common Angular Mistakes 

“Forgetting” or simply ignoring this issue. 

And you have no “excuse”, you know, for overlooking to clean up your subscriptions in Angular. Considering that there are methods and libraries developed precisely for handling these unsubscriptions once you've finished using an event or an observable in JavaScript.

Why does this “clumsiness” risk to grow into a major issue? Because lingering subscriptions cause memory leaks in your system.

And when it comes to the unsubscription process, there are 2 scenarios:
 

  1. you trigger the OnDestroy lifecycle hook if it's in a component that you've subscribed in
  2. you initiate the lifecycle hook yourself if it's a service that you've subscribed in (since, in this case, there's no available hook for you to fire)
     

To recap: Remember to unsubscribe when you no longer use a service/component!
 

3. The Wrong Use of Providers

One of Angular's (compared to AngularJS) key improvements is its Hierarchical Dependency Injection, agree?

This means that now you're free to instantiate a service several times (services used to be singletons back in the AngularJS's “glory days”, remember?).

Now that being said, let's have a look at a more than likely scenario:

Imagine yourself fetching your heroes using a heroes service:
@Injectable()

export class HeroesService {

heroes: Hero[] = [];

constructor(private http: Http) {

this.http.get('http://give-me-heroes.com').map(res => { 

return res.json(); 

}).subscribe((heroes: Hero[]) => {

this.heroes = heroes;

});

}

getHeroes() {

return this.heroes;

}

}

Nothing unexpectedly wrong till here:
 

  • the data is being fetched in the constructor
  • there's also a getHeroes method for retrieving the heroes 
     

Now, let's take a look at the hero component, too:

@Component({


selector: 'hero',

template: '...',

providers: [HeroesService]

})

export class HeroComponent {

constructor(private heroesService: HeroesService) {}

}

@NgModule({

declarations: [HeroComponent]

}

export class HeroesModule { ... }

As you can see, first the HeroComponent declares the HeroesService provider in the @Component.providers array, next it incorporates it in the constructor. 

All well and good till you realize that each HeroComponent instance instantiates a new instance of the HeroesService. 

To put it more simply:

Your HeroesService will be fetching the data (by HTTP request) several times, for each and every HeroComponent instance!

And this is due to the Hierarchical DI in Angular.

The solution for avoiding this issue — no doubt one of the most common Angular mistakes? 

Declaring the service in the @NgModule.providers instead:
@Component({


selector: 'hero',

template: '...'

})

export class HeroComponent {

constructor(private heroesService: HeroesService) {}

}

@NgModule({

declarations: [HeroComponent],

providers: [HeroesService]

}

export class HeroesModule { ... }

There! The provider will now be instantiated once and for all. “For all” the HeroComponent instances I mean.

“How come?” You might ask yourself.

Because the provider (declared in the NGModule now) is a singleton now. Therefore all the other modules can use it.
 

4. Manipulating the DOM Directly

Although I've already said this about another mistake from this list, I now tend to consider this one here instead as being one of the most common Angular mistakes:

Manipulating the DOM directly; oftentimes from the controller itself!

And this is one of those top 10 Angular mistakes that any developer stands a high risk of making. Since manipulating the DOM is such a common task when using this platform:
 

  • you might need to render SVG
  • you might need to refresh a page's title based on a context change
  • you might need to set the focus on a control after a validation error
  • … and the list of possible situations goes on
     

Then... you fall right into it: you take the easy way out and hack the DOM directly!

Now what I feel like pointing out it here is that:

Angular's grown from a web framework into a platform!

And this can only mean that you're now free to decouple your Angular application's codebase from the renderer and:
 

  • have your app executed in on the server
  • … in the browser
  • … as a native app 
     

And decoupling opens the door to other possibilities for you to explore and to tap into, such as using web workers or AOT (ahead of time compilation).  

Speaking of the latter:

AOT enables you to compile your app's templates in the build time of your server. Moreover, you won't need to use the oversized @angular/compiler package in your bundle, which leads to a lower size and load time.

Yet, for future-proofing these “facilities” that Angular provides, you'll need to abide by... some sort of rules at least. And one of them is:

Restraining yourself from manipulating the DOM directly, using jQuery, the global document object or the ElementRef.nativeElement.

Instead, use the Renderer2 service (or Renderer for Angular 2):

It's 2 things that this wrapper to the view mutation layer will enable:
 

  1. for the default layer to be used in the browser
  2. for the renderer to get replaced with a more suitable one whenever your Agular app runs on another platform (e.g. a phone)
     

In short: Resist “temptation” and never ever touch the DOM directly!
 

5. Declaring The Same Component in More than Just One NgModule 

And declaring a component in multiple NGModule-s is one of those most common Angular mistakes that end up throwing an error “at” you.

“Why, so?”

Because you need to declare each component in its own NgModule — and to list it in the @Ngmodule.declarations array — in order for it to be available for the views. 

If you do need to declare the very same component in multiple modules, you'll need to consider the relationship between those modules:

Is it a parent-child one, maybe?

If this is the case, then:
 

  • use the child's NGModule.declaration to declare the HeroComponent in the child module
  • use the chid's NGModule.exports array to... export the HeroComponent 
  • use the parent's NGModule.imports array to import the child module 
     

If not (if we can't be talking about a parent-child module relationship), then you'll need to declare another NgModule as the module of the shared data.
 

Final Word 

It's only by knocking your head against unexpected issues while building your projects on this platform, that you'll get to grow as an Angular developer.

And still, instead of embracing the “fail fast, fail often” concept, wouldn't it be best if you:
 

  • learned from other developers' mistakes, thus knowing what the most common Angular mistakes are  
  • ensured that you failed "rarely" instead?

Recommended Stories

What Is the Best Way to Port an Android App to iOs and Vice Versa? 5 Aspects to Consider 
If only there was a... button that you could just press to convert your app to Android or iOS, right? Or if only a… (Read more)
Adrian Ababei / Jun 21 '2018
How to Fix a Hacked WordPress Site: A Step-by-Step Guide on Identifying and Removing Malware
“Mysterious” pop-ups that you did not initiate, inexplicable auto-linking keywords, frequent freezing of your… (Read more)
Adriana Cacoveanu / Jun 19 '2018
What Is the Best Way to Style React Components? 4 Most Widely-Used Approaches to Styling
Sorry to disappoint you, but: there's no such thing! No such thing as “the best way to style React components”. Or… (Read more)
Adrian Ababei / Jun 14 '2018