How to generate documentation for Angular applications?

Documenting software is hard. Not only that, maintaining software documentation is even more complicated and often forgotten.

What’s the solution, then? What about using an automated solution that:

  1. Generates documentation from code comments and does not require a Wiki or any third-party software.
  2. Generates said documentation automatically and can be part of your build process.
  3. Gives metrics and feedback to developers to encourage them to write more documentation.

Such a solution exists. It’s called Compodoc. Compodoc can generate a Javadoc-like website from all the comments written in your application (you can see an example of such documentation here):

Compodoc can be installed globally with npm:

npm install -g @compodoc/compodocCode language: CSS (css)

Or you can add it locally to a single Angular project by running the ng add schematic in your project folder:

ng add @compodoc/compodocCode language: CSS (css)

Then you can create a config file to decide which files to include in the documentation (for instance, you might want to exclude test, and Compodoc is ready to run with a single command:

npx compodoc -p tsconfig.doc.jsonCode language: CSS (css)

The above command creates a static HTML website documenting your entire application with all modules/components/pipes/directives/services.

My favorite feature is the documentation coverage statistics that show which parts of the application are well-documented and which are not, using a report similar to test coverage reports that developers are familiar with.

Formatting functions in Angular

We mentioned the default config options for the date pipe in Angular yesterday.

Did you know we can also format dates in our Typescript code using a formatDate function?

This function has the same signature as the date pipe, which makes perfect sense because… That’s the function used by the pipe itself (source code here):

formatDate(value: string | number | Date, 
           format: string, 
           locale: string, 
           timezone?: string): stringCode language: JavaScript (javascript)

All you need to use that function is to import it from @angular/common:

import {formatDate} from "@angular/common";Code language: JavaScript (javascript)

The only downside of that function is that there is no default format or locale, so we have to pass those two values as parameters, which isn’t the case for the date pipe.

And by the way, similar functions are available for numbers, currencies, and percentages:

For more information on those functions, I have this tutorial on formatting dates and numbers with Angular.

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.

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.