This article is for versions of Angular 2, Angular 4 and later.

In Angular we have the availability to use TypeScript and editor tools that can statically analyze our components. This provides autocompletion feedback and can detect typos in our templates. In this post we will cover a couple of tricks that can help prevent pesky typos in our HTML templates and catch errors at build time rather than run time.

A common use case is toggling the visibility or CSS class of a DOM element. Usually we toggle this information on some kind of type or state. For example in our app we have different notification messages we want to display to the user such as a error or sucess message.

In our example we will toggle the visibility and styles of the element based on the type. In our use case we have a message component to display messages to users in various states. Our message states are the following: Success, Error, Warning, and Default.

Angular Message Component

Static Analysis

Our message component has two inputs. First it takes the message type, example error vs success. The second input is included via ng-content is the actual message we would like to display. Lets take a look at the message component below.



import { Component, Input, OnInit } from '@angular/core';

export enum MessageTypes {
  Default,
  Success,
  Error,
  Warning
}

@Component({
  selector: 'app-message',
  template: `
    <div class="message" [ngClass]="{
      'message--error': messageTypes.Error === type,
      'message--success': messageTypes.Success === type,
      'message--warning': messageTypes.Warning === type
    }">
      <ng-content></ng-content>
    </div>
  `
})
export class MessageComponent implements OnInit {
  @Input() type = MessageTypes.Default;
  private messageTypes = MessageTypes;

  constructor() { }

  ngOnInit() { }
}



Our component has the one input for the type of message to display and then displays the content with the ng-content feature. Ng content takes whatever content we place in the component tags and inserts it into our template. We will see this in just a moment.

The important thing to notice in our component above is our enum we are using for the message types. Using a enum we can bind the enum to our component property.



export enum MessageTypes {
  Default,
  Success,
  Error,
  Warning
}


What does this give us? We can now reference a property in our templates instead of magic strings.



<div class="message" [ngClass]="{
  'message--error': messageTypes.Error === type,
  'message--success': messageTypes.Success === type,
  'message--warning': messageTypes.Warning === type
}">
  <ng-content></ng-content>
</div>


Now if refactor our code there or no magic string duplicated across our code base and we can rename and refactor as needed.

Editor Autocompletion

This technique also makes it easier to use our components and understand the API signatures. Below is my component that is using the app-message component.



import { Component } from '@angular/core';

import { MessageTypes } from './message.component';

@Component({
  selector: 'demo-app',
  template: `
    <app-message [type]="messageTypes.Error">
      Error: Hello World
    </app-message>
  `
})
export class AppComponent {
  messageTypes = MessageTypes;
  constructor() { }
  
  ngOnInit() { }
}

</div>


We can see we bind the message type enum to our demo component. Now in our templates we will get static typing and our editor can provide auto completion like below.

Taking advantage of TypeScript and Angular template syntax we can help lower the chances of production run time errors and catch them early in development. Check our the working demo below. To see the template static type checking in action copy the demo into a editor with TypeScript support like Visual Studio Code.

Demo