ngOnInit lifecycle hook

A few days ago, we talked about the ngOnChanges lifecycle hook. We saw that every time an @Input() changes, Angular will trigger ngOnChanges. ngOnInit is similar but runs only once; after all @Input() receive their initial value. The official documentation puts it like this:

The above definition might surprise you because there is a widespread belief that the purpose of ngOnInit is to run all initialization tasks, even though the class constructor runs before ngOnInit, as explained a few months ago in this entry: ngOnInit vs. constructor in Angular.

As a result, using ngOnInit is only 100% justified when you want to run some code that needs the value(s) of @Input() properties of your component/directive. In other scenarios, you can use a constructor to run your initialization code sooner.

How to create custom pipes?

Earlier this month, we covered how to create custom directives. Today, let’s tackle how to create custom pipes. Pipes help format data such as strings, dates, numbers, etc. The first thing to do is to use the Angular CLI:

ng generate pipe [name]

or ng g p [name]

It’s also possible to generate standalone pipes with the --standalone option:

ng generate pipe [name] --standalone

This creates a class with a single method transform to implement:

By default, the types are all set to unknown, as Angular CLI cannot guess what kind of data we want to format. As we know what we want to format and how, as well as how many arguments our pipe can accept, we can change that signature to make it more meaningful as follows:

Most pipes have optional parameters, so it’s always a good idea to have a default value for each, as I did in this example with displayPrefix = true.

Assuming we change the name of the pipe in the decorator to personName, such a pipe can safely be used as follows:

Or, if we want to turn off the prefixes, we can use our optional parameter and set its value to false:

Displaying an overlay with Angular

We covered how to display a dialog in two lines of code earlier. Today, I want to illustrate how we can show an overlay on any portion of the screen using the Angular CDK.

First, it’s important to mention that Angular CDK is NOT part of Angular Material, and you can use the CDK independently from any component library.

To install the CDK: npm install @angular/cdk

Then, you would import the OverlayModule wherever you need it (here in a standalone component):

This module allows you to inject an Overlay service that can be used to create an overlay and display a component in it:

By default, overlays have a transparent background, so I added a panelClass for my overlay and then gave it a background color – Note that you also need to import the CSS styles from the CDK in your global CSS file:

There are plenty of configuration options, and if you want to see a different approach, look at this tutorial for a dropdown built with an overlay. The source code for my basic example is here on Stackblitz.

ngOnChanges lifecycle hook

ngOnChanges is an Angular lifecycle hook that is called whenever one or more of the bound input properties of a component changes. This hook helps update the component’s state or view in response to changes to the input properties.

To use it, implement the OnChanges interface as follows:

The above ngOnChanges method will run every time the parent component updates the value of name. We can get more information about what changed using the parameter of that method, an object that maps each changed property name to an SimpleChange object. The SimpleChange object contains the following properties:

  • previousValue: The value of the property before it changed.
  • currentValue: The value of the property after it changed.
  • firstChange: boolean value, true if it’s the first change made to that input, false otherwise.

As an example, the above code would output that object to the console as follows:

You can find that example in action on Stackblitz. The most common real-life example of using ngOnChanges is to be notified when an object ID changes so the component can request data for that ID using a service that makes an HTTP request, for instance.

Best practices for using visibility modifiers

Yesterday, we talked about Typescript visibility modifiers in the context of Angular classes. Today, I want to focus on best practices and common scenarios that involve such visibility modifiers.

First, it’s very common to have Angular services that use RxJs Subjects. Subjects are somewhat dangerous because they can be used to emit data to all subscribers. As a result, it makes sense to “hide” a subject by making it private and then expose an Observable out of it as follows:

Note that we don’t need to make data$ public, because any field that isn’t private or protected is public by default. Using readonly enforces that other components/services cannot assign a new value to data$. As a result, the above code is safe: The business logic that decides when and how to emit data is “hidden” in our service (where it belongs), and yet the rest of the application can be notified when the data changes without being able to break that process by accident.

Of course, the same idea applies to Signals (see my best practices for Signals)

Another option suggested in that post is to define a getter method that returns the read-only object:

This is equivalent to using readonly. The value can’t be changed because we define a getter and no setter.

Let’s complete our best practices list from yesterday:

  1. Make every member private by default
  2. If the member is needed in the template of a component, make it protected
  3. If the member is meant to be fully public, go with public
  4. If the member should be accessible but not modifiable, use readonly or a single getter with no setter

Typescript visibility modifiers

Angular is mostly about Typescript classes, and Typescript classes have modifiers that alter the visibility of class members: public, protected, private, and readonly. Here is what you need to know about them.

Everything is public by default

If you don’t use a modifier on a class member, it is public by default. Any other class can see and use that member and change its value:

private means that the member isn’t visible outside of the class (including a component’s HTML template)

private is a way to enforce that other classes cannot access a member of your class. Used in a component, this indicates that we do not want that property to be used in the component’s HTML template. In a service, this suggests that we don’t want other components/services to see that member:

protected is in-between public and private. It makes the member accessible in a component’s template without making it fully public.

In the following example, our component property date is invisible from other Angular code in our app, but our HTML template can use it:

Best practice – My recommendation

If you want to stick to simple rules that make sense and are the safest, here’s what you can do:

  1. Make every member private by default
  2. If the member is needed in the template of a component, make it protected
  3. If the member is meant to be fully public, go with public

Tomorrow, I’ll add a couple more suggestions by introducing the readonly modifier. Stay tuned!

ngSwitch directive

The ngSwitch directive is a good alternative to ngIf if you have to handle more than two scenarios.

It works similarly to a switch statement in traditional programming languages, allowing you to define a set of cases and associate each case with a specific template block to be rendered. For instance:

One of my favorite use cases is for basic pagination in a component (or an image carousel, for instance) where clicking on navigation buttons changes a value that triggers a different “case”:

Clicking on the buttons changes the value of page and displays a different template. Applying this to components instead of HTML elements is especially powerful. For instance: <app-hello *ngSwitchCase="3"></app-hello>

You can see an example in action on Stackblitz here.

RxJs Timer for recurring tasks

You’re probably familiar with setTimeout (to run some code after a given timeout) and setInterval (to run some code at a given time interval). Both are “native” Javascript functions and can be used with Angular.

That said, recurring code execution is asynchronous, and asynchronous work is often done with RxJs in Angular apps. As a result, let’s talk about a 100% RxJs way to replace setTimeout and setInterval.

The RxJS timer operator creates an observable that emits a value after a specified delay. The delay can be specified in milliseconds or as a Date object.

The following code creates an observable that emits a value (0) after one second:

If we want timer to emit immediately and then keep emitting at a given interval, we can do the following:

This would emit 0 immediately, then 1 five seconds later, 2 ten seconds later, etc. Most of the time, we don’t care about the emitted number. We want to turn that Observable into another one (like an HTTP request, for instance) using our good friend switchMap:

What’s the benefit of using timer in such scenarios? We get automatic unsubscriptions if we use the async pipe or the takeUntilDestroyed operator.

Here is a tutorial for a concrete example of how to do HTTP polling with Angular and the timer operator.