Date pipe default format and timezone

The date pipe is the most convenient way to format dates with Angular. However, very often, we need to use a consistent date format throughout our application, which means that we have to pass that custom format every time we use the date pipe:

<span>Today is {{today | date: 'MM/dd/yy'}}</span>Code language: HTML, XML (xml)

Of course, we could store that format in a constant and reuse that constant every time we use the pipe, but that’s not very convenient.

Luckily for us, since Angular 15, we can now set a default date format (and timezone) by configuring a new injection token called DATE_PIPE_DEFAULT_OPTIONS.

It works by adding the following code to your dependency injection config (array of providers) in app.modules.ts:

providers: [
  {
    provide: DATE_PIPE_DEFAULT_OPTIONS, useValue: {dateFormat: 'MM/dd/yy'}
  }
]Code language: JavaScript (javascript)

With such a config in place, we can use our pipe without any parameters and have our default formatting applied automatically in our entire application:

<span>Today is {{today | date}}</span>Code language: HTML, XML (xml)

The timezone can be customized as well with the timezone property of that same DatePipeConfig object.

The debugger keyword

Yesterday, we covered how to use the JSON pipe with a <pre> tag to debug JSON data on a web page.

Today, I want to cover one more debugging technique that is another time saver: The debugger keyword.

Whenever you want to add a breakpoint in your web application, add the Javascript instruction:

debugger;Code language: JavaScript (javascript)

Then open the dev tools in your browser and navigate to your application URL. Whenever Javascript hits that debugger statement, the runtime will stop on that breakpoint, allowing you to debug your code:

Once the browser is paused on that breakpoint, you can add other breakpoints by clicking on the line numbers in the browser dev tools, just like regular debuggers work.

Two important things to note:

  1. The breakpoint works only when the dev tools are open
  2. Don’t forget to remove the debugger statement once you’re done debugging. You probably don’t want to ship that one to production.

Debugging with the JSON pipe

We have all used console.log at some point to debug our code. With Angular, there is an interesting alternative to display debugging information on our web page temporarily: The JSON pipe.

The primary usage is as follows:

<span>myData | json</span>Code language: HTML, XML (xml)

The above code will output your data as a JSON string in the span element, but it won’t be formatted, so the JSON string can be hard to read:

{"affiliation":"friendly","symbol":"Default Land Unit","echelon":"none","mod1":"None","mod2":"None","uniqueDesignation":"","higherFormation":"","reinforcedReduced":"","flying":false,"activity":false,"installation":false,"taskForce":false,"commandPost":"None","tacticalMissionTasks":"None","type":"Land Unit"}Code language: JavaScript (javascript)

Instead, the following syntax works a lot better:

<pre>myData | json</pre>Code language: HTML, XML (xml)

The pre HTML tag stands for “preformatted” content. As a result, that tag will preserve any whitespace, new lines, and tabs, which makes reading that JSON data a lot easier:

{
 "affiliation":"friendly",
 "symbol":"Default Land Unit",
 "echelon":"none",
 "mod1":"None",
 "mod2":"None"
}Code language: JavaScript (javascript)

It’s a simple trick, yet a big time saver when debugging code that’s using complex JSON structures.

RxJs switchMap operator

A common mistake made in Angular applications is to nest observable subscriptions in the following manner:

observable1.subscribe(data => {
   observable2.subscribe(otherData => {
     // Do something with otherData
   });
});Code language: JavaScript (javascript)

The above syntax is not recommended because it is hard to read and can lead to subtle bugs and unexpected side effects. For instance, that syntax makes it difficult to unsubscribe properly from all these observables.

Also, if observable1 emits more than once in a short amount of time, we might want to cancel the previous subscription to observable2 and start a new one based on the new data received from observable1. The above code does not do any of that.

The solution: Use the RxJs switchMap operator like so:

observable1.pipe(data => {
   switchMap(data => observable2)
).subscribe(otherData => {
     // Do something with otherData
});Code language: JavaScript (javascript)

The switchMap operator does all of the following:

  • Automatically cancel and unsubscribe from observable2 if observable1 emits a new value.
  • Automatically unsubscribes from observable2 if we unsubscribe from observable1
  • Makes sure that observable1 and observable2 happen in sequence, one after the other.

The following marble diagram is a good illustration of what switchMap does:

If you’re not using switchMap yet, look in your code for nested calls to .subscribe(), and you can start replacing those with the switchMap operator to prevent memory leaks and bugs and make your code more readable.

Here is a link to an example that uses a timer to make HTTP requests every 30 seconds to get updated data. The timer data is turned into an API call using switchMap on line 37 of the example.

Exported Directives

Yesterday, we talked about Template Reference Variables. Today, I want to show you how a directive can be accessed with a Template Reference Variable.

You’ve probably seen that syntax before:

<form #myForm="ngForm" (ngSubmit)="onSubmit(myForm)" >Code language: HTML, XML (xml)

That syntax is possible because the NgForm directive is exported using the following syntax (actual Angular source code here):

@Directive({
   exportAs: 'ngForm'
})Code language: TypeScript (typescript)

The above code enables the usage of Template Reference Variables such as #myForm="ngForm" . This technique is widely used in Angular forms and component libraries to expose public directive properties (and methods) to your component’s template.

For instance, we can access myForm.value or myForm.valid in an expression.

ngModel is exported that way, too.

Template Reference Variables

Welcome to the very first edition of my daily Angular Newsletter! As promised, I’ll keep it nice and short.


Today’s topic is Template Reference variables. I usually call that feature “the hashtag syntax” because that’s how it’s used:

<input #phone placeholder="phone number" />Code language: HTML, XML (xml)

Here’s how I could use that reference variable to get the value of the input, for instance:

<button (click)="callPhone(phone.value)">Call</button>Code language: HTML, XML (xml)

phone refers to the input element with the #phone attribute created earlier. That’s the template reference variable.
These variables can be used instead of ngModel, for instance. Even better, they also work with components and directives!

For instance, the following template reference variable hello would have access to all public properties and methods of the HelloComponent:

<app-hello #hello ></app-hello>Code language: HTML, XML (xml)

For more information and examples, you can read another short blog post of mine here.