5 tips to boost your Angular skills
Check out these advises backed by concrete examples which can help you improve your developer skills and give you some practical tricks.

This summer me and Roman started a series of tweets with helpful tips and tricks about Angular. It was met well by the community so I decided to write an article follow-up. Here are 5 generalized advises I want to give to Angular developers across the globe. These advises are backed by some concrete examples pulled from our Twitter activity. They can help you improve your developer skills or give you some practical tricks at the very least.
1. Know how change detection works in Angular
There are many great articles going deep into change detection mechanism. Like this one. So let’s just recap the basics quickly and get to the tips.
Recap
Angular has two change detection modes: Default
and OnPush
. First one triggers change detection for every tick happened anywhere in the app. Second only marks view for checking if an event has happened in this view or if input data has changed.
Default vs OnPush
There’s really no reason for you to use Default
. All you need to do is write your code the way framework expects it to and you won’t get into trouble with OnPush
. This means, you should never mutate your data. If your input arrays or objects change immutably, OnPush
would pick this up and refresh the view.
When you subscribe to events with @HostListener
Angular has got you covered as well. But what if you are working with RxJS streams? You can always inject ChangeDetectorRef
and do markForCheck()
when you need it. But a declarative option would be to end up with async
pipe in your template. It would trigger change detection on each emit.
You might have seen this pattern:
<div *ngIf="stream$ | async as result">
...
</div>
But what do you do when you need falsy results too? You can strip condition logic from ngIf
and create a simple structural directive. It would be used only to add context to the view:
?#AngularTip for the day! Like declaring async results with *ngIf="stream$ | async as result" but need to support falsy values? Here's a simple #angular directive that does just that! ?https://t.co/4DR9pdZsIc pic.twitter.com/E9rjPwnnAn
— Alex Inkin (@Waterplea) June 4, 2020
NgZone
If you cannot fully switch to OnPush
there are still things you could optimize. You can inject NgZone
and do performance sensitive actions in .runOutsideAngular()
. This way there will be no extra ticks in the change detection mechanism. Even components with Default
strategy will not perform change detection cycle. You should do this for events that trigger rapidly like mousemove
, scroll
. To do it declaratively with RxJS streams you can create two operators. One for leaving the zone and another to return to it if you need to trigger change detection:
?#AngularTip for the day! Manage NgZone in your #RxJS streams to avoid extra ticks in you #Angular app with these 2 simple operators??
— Alex Inkin (@Waterplea) June 8, 2020
Code: https://t.co/GwoCJYLTYp pic.twitter.com/1SdcJQrwQl
Another option you can have with @HostListener
decorator is custom event manager plugin. We released an open-source library called ng-event-plugins. It allows you to filter out unnecessary change detection cycles. Read more about it in this article.
2. Learn RxJS. Seriously!
RxJS is a very powerful tool. We all use it to some extent when working with Angular but really mastering it can help you a lot. From very simple streams that allow you to reload your component…
?#AngularTip for the day! Create a simple #RxJS stream to quickly reload your #Angular component♻️ pic.twitter.com/e7OaTNgL2A
— Alex Inkin (@Waterplea) June 29, 2020
…to complex operators combination. Like this example recognizing various types of scroll:
?#AngularTip for the day! Learn how to differentiate regular scroll from momentum scroll in your #Angular app on mobile with #RxJS?
— Alex Inkin (@Waterplea) June 28, 2020
Live demo: https://t.co/5egs6gXexp pic.twitter.com/3eQQcWCzg5
Just take a look how easy it is to create a sticky header that disappears when you scroll down. A little bit of CSS and pretty basic RxJS:
?#AngularTip for the day! Create an #Angular directive for sticky header that disappears when you scroll down?
— Alex Inkin (@Waterplea) July 15, 2020
Live demo:https://t.co/wli6vAnf9G
WINDOW token from our library:https://t.co/kgfN68QtIy
Unsubscribe with destroy service from this tweet: https://t.co/7fdQgJTFLB pic.twitter.com/Xlc2je9Kny
I cannot stress enough how important RxJS knowledge is to an Angular developer long term. While it’s simple on the first look, RxJS requires a little bit of paradigm shift. You need to start thinking in terms of streams. But once you do, your code would become more declarative and easier to maintain.
There is not much I can suggest here other than practice. If you see a case that you can solve with RxJS — try to do so. Avoid side-effects and nested subscribes. Keep your streams organized and watch out for memory leaks (read further).
3. Max out TypeScript
We all use TypeScript in our Angular applications. But to get the most of it we need to push it to the limits. I rarely see projects with enabled strict: true
. This is something you totally should do. It will save you from lots of cannot read property of null
s and undefined is not a function
s.
Generics
In TypeScript we can use generics when the type we work with is unclear. Combination of generics, overloads and type narrowing can make a pretty solid API. You almost never will have to typecast. Take a look at this example of strongly typed RxJS method fromEvent
:
?#AngularTip for the day! Tired of typecasting event target or defining event type for #RxJS method 'fromEvent'? Add custom type and a typed wrapper function!?
— Alex Inkin (@Waterplea) June 20, 2020
Live example: https://t.co/Uo003HLZ0x#Angular #TypeScript #100DaysOfCode #developer pic.twitter.com/CbdQj424I3
With it you can be sure that target in the event has the same type as the element you listen the event on. And event has properly narrowed type.
Generics based APIs have the benefit of being data-model agnostic. This means people can use it without being forced to a particular interface
There are articles dealing with things like type inference, advanced types, unions. I suggest you educate yourself in the subject, it would help you make robust code in the long run. My one last advice here is never use any
. You can almost always replace it with generic or unknown
which is a safer version of any
.
Decorators
Don’t forget about other TypeScript features, such as decorators. When used well, they can really improve your code. There are cases when type is correct, but logically value is unacceptable. Like when you have a number
input for quantity — you cannot really have negative or decimal values. But according to TypeScript they are correct. You can protect your components for such invalid inputs with assertion decorator:
?#AngularTip for the day! Protect your #angular components from illegal but properly typed inputs with assertion #TypeScript decorator?
— Alex Inkin (@Waterplea) June 7, 2020
Code: https://t.co/8P4SANVnjx pic.twitter.com/pwJVGgFevt
Did you know that if you decorate your abstract classes you do not have to pass arguments to super()
? Angular will handle it for you:
?#AngularTip for the day! If you decorate your abstract class, #Angular will resolve constructor parameters and you do not need to add constructor to concrete implementation!?️ pic.twitter.com/hUwz671iPF
— Alex Inkin (@Waterplea) June 13, 2020
Another good case for custom decorator is some reusable processing logic. For example, in our Web Audio API library for Angular we turn declarative input bindings to imperative native commands with a strongly typed decorator:
You can read about this library in detail here
4. Angular’s DI is king! Use it. Then use it more!
Dependency Injection is part of the reason Angular is such a powerful framework. Arguably it is THE reason. Too often it is not used to its full potential.
Head over to this dedicated article about DI we wrote to deepen you knowledge about it
RxJS
When it comes to practical advises, I mentioned before to watch out for memory leaks in your RxJS streams. Mainly this means: if you manually subscribe to a stream you need to unsubscribe yourself. An idiomatic solution in Angular would be to encapsulate this logic into a service:
?#AngularTip for the day! Create a simple #RxJs Observable service to encapsulate destruction logic of your #Angular components and directives? pic.twitter.com/iD8uLvl9x3
— Alex Inkin (@Waterplea) June 11, 2020
You can also create shared streams and add them to DI tree. There’s no reason to have separate requestAnimationFrame
based Observables across the app. Create a token for it and reuse. You can also add zone operators discussed above to it:
?#AngularTip for the day! Create a shared requestAnimationFrame-based #RxJS Observable to use across your #Angular app⏱️
— Alex Inkin (@Waterplea) June 26, 2020
ℹ️ or just use our opensource library of tokens for native APIs: https://t.co/kgfN6984A6 pic.twitter.com/Drj7YL9RHd
Tokens
DI is also a good way to make your components more abstract. If you do not rely on global objects, such as window
or navigator
— you are ready for Angular Universal which renders you app on the server side. As you know, node.js does not have DOM and many of the global objects we are used to. It is also much easier to test such code because dependencies are effortlessly mocked. It is not difficult at all to tokenize these objects. We can use factories when we define injection token and top level injector is available to us. Using built-in DOCUMENT
it takes just a few lines to create WINDOW
token:
?#AngularTip for the day! You can use 'inject' method from '@angular / core' in the context of a factory function to reach for type-safe dependencies for #angular injectable. Here's how easy it is to tokenize global window!?
— Alex Inkin (@Waterplea) June 5, 2020
Read more: https://t.co/abP7GNgsie pic.twitter.com/5Y7eVBX2xg
To save time, use this open-source library where we already created some of those tokens. There’s also its Angular Universal counterpart with mocks. Feel free to request other tokens to be added!
Tokens and factories are very powerful tools. Combined with hierarchical nature of dependency injection they can help you make your app very modular. Read more about clever use of providers in this article.
5. Throw emperor down the abyss. Like Vader.
Angular with its template bindings and decorators clearly pushes us to write declarative code. I’ve mentioned this approach above. I will not get into discussion of benefits it has over imperative code here. Instead I’ll give you a solid advice: write declarative code. When you get used to it, you’d appreciate it.

Getters
What does it mean to write declarative code? First of all, try to use ngOnChanges
as rare as you can. It’s a poorly typed side-effect which is really only needed if you must perform an action upon multiple inputs change. On a single one a setter is a more streamlined solution. And if instead of action you wanted to update some internal state, think if you can remove that manual state and replace it with calculated getter.
Performance and getters is a subject for a separate article which I hope to get to writing soon. For now, just take a rule of thumb to not create new arrays or objects in getters. If you need to calculate a new object, use memoization techniques like pipes, for example.
?#AngularTip for the day! Sparkle come #CSS variables magic over your #Angular app and create isolated themes with 1 line of code!?
— Alex Inkin (@Waterplea) July 16, 2020
Live demo: https://t.co/Brm3Lr4Zq6
?Be careful though! Angular style binding does not sanitize content! pic.twitter.com/MzZkxmprFY
Here’s a good case for a setter which I’ve omitted for the brevity of the example (but was reminded of by an attentive follower).
Template reference variables
Instead of manually requesting elements for the view, Angular has @ViewChild
decorator. Quite often though, you don’t really need it if you can enclose logic in the template:
<input #input>
<button (click)="onClick(input)">Focus</button>
Here we pass template reference variable directly to the method where we need it. This makes our component code clear. Think of it as sort of a closure in a template. But what do we do if we need a DOM element of an underlying component? We could have @ViewChild(MyComponent, {read: ElementRef}
but we can do this without decorator if we create a directive with exportAs
:
?#AngularTip for the day! Ever needed to get #HTML element behind your #Angular component with a template reference variable? Write a simple directive to expose it!? pic.twitter.com/XfFtcQsGXT
— Alex Inkin (@Waterplea) June 9, 2020
Dynamic content
People often use ComponentFactoryResolver
to create dynamic components imperatively. Why, if there is ngComponentOutlet
directive? Because this way you have access to the instance and can pass some data to it. A proper way to solve this issue is, once again, dependency injection. ngComponentOutlet
allows you to pass custom Injector
which you can create with data provided through token.
In fact, to create dynamic content you have interpolation, templates and components. And there is not much difference between these approaches. You have context and your have a representation:
?#AngularTip for the day! When creating customizable #Angular components, think in terms of content and context, not in terms of templates, functions, literals. Check out my #opensource project that acts as interpolation, template & component outlet!?https://t.co/piqcF8uujb pic.twitter.com/xINZsRuxjE
— Alex Inkin (@Waterplea) June 30, 2020
I’ve been using this content-agnostic approach to customizable components for a long time. We’ve released a tiny open-source library called ng-polymorpheus. It doesn’t do anything really, just pass content to the proper built-in Angular tool, be it ngTemplateOutlet
, ngContentOutlet
or simple function interpolation. Once you get used to it, there’s no going back!
This wraps it up for this article. Hope you would find these tips useful!
If you like this, you can check all of our tips. We also wrote an advanced Angular handbook which we continue to develop over at angular.institute. Happy coding!
Bonus
A simple tip that was received unexpectedly well is Luhn algorithm in form of an Angular Validator. So if you are working on some application where users enter their credit card number, you can use this code to check its validity ?
?#AngularTip for the day! Create #Angular validator to check validity of entered card number with Luhn algorithm? pic.twitter.com/QdPPpCqwdK
— Alex Inkin (@Waterplea) June 22, 2020