How to use an Enum in an Angular Component

In our previous article, we have implemented user email verification based on a short-lived token. In this scenario, the token can have a different status like Valid, Invalid, Expired, etc., and based on this status, we had to render the view page. Hence, we have used an Enum for this use case to hold the different types of status. Now let’s dive deep to understand how to create a TypeScript Enum and use it in Angular components.

What is an Enum ?

Enums are one of the few features TypeScript has which is not a type-level extension of JavaScript. Enums allow a developer to define a set of named constants. Using enums can make it easier to document intent, or create a set of distinct cases. TypeScript provides both numeric and string-based enums.

Creating an Enum

We can either create the enum in a separate file or on the same component file outside the class. In our example, we have created the enum in the same token.component.ts file as shown below:

export enum TokenStatus {
	  VALID,
	  INVALID,
	  EXPIRED,
	  SENDING,
	  SENT
	}

Using an Enum in an Angular Component

After creating the enum, we need to create a field in the component where we want to use this enum and assign it to the field:

tokenStatus = TokenStatus;

Then, create a new field of type TokenStatus to hold the current status of the token:

status : TokenStatus;

Then, assign a value to the status field,

this.status = TokenStatus.VALID;

Then, in the component HTML file,

<div class="form-group" *ngIf="status == tokenStatus.VALID">
		<div class="alert alert-success" role="alert">Email verified successfully. Please login.</div>
</div>
<div class="form-group" *ngIf="status == tokenStatus.EXPIRED">
	<div class="alert alert-danger" role="alert">Link Expired!</div>
	<button class="btn btn-primary btn-block" (click)="resendToken()">Re-send Verification Email</button>
</div>

Convert a String to Enum in TypeScript

In our application, we are validating the token in the backend REST API and getting the validation result in the response. This result will be VALID/INVALID/EXPIRED. Hence, instead of manually checking the string result returned in the JSON response, we have directly assigned the string value to the status field with the help of keyof and typeof operators. Now let’s understand what these operators are.

In Typescript, enums are used as types at compile-time to achieve type-safety for the constants but they are treated as objects at runtime. This is because they are converted to plain objects once the Typescript code is compiled to Javascript. Hence, in order to dynamically access an enum by a string key, we need to use the combination of keyof and typeof operators.

The keyof operator takes an object type and returns a type that accepts any of the object’s keys. it will return a union of string literals, each one is the key in the given object.

The typeof type operator can be used in a type context to refer to the type of a variable or property.

this.status = TokenStatus[data.message as keyof typeof TokenStatus];

Here, the typeof would return the type {VALID:string, INVALID:string, EXPIRED:string, SENDING:string, SENT:string} and the keyof will return a union of literal types ("VALID" | "INVALID" | "EXPIRED" | "SENDING" | "SENT") that is made from the properties of type TokenStatus.

Note: Though Enums are treated as objects at runtime, when I tried with just the keyof operator, it worked fine. I couldn’t find an answer to this behavior. If you know, please do leave it in the comments section.

this.status = TokenStatus[data.message as keyof TokenStatus];

Token Angular Component Code

Here is the complete working code of the token component.

token.component.ts

import { Component, OnInit } from '@angular/core';
import { AuthService } from '../_services/auth.service';
import { Router, ActivatedRoute } from '@angular/router';

export enum TokenStatus {
	  VALID,
	  INVALID,
	  EXPIRED,
	  SENDING,
	  SENT
	}


@Component({
selector: 'app-token',
templateUrl: './token.component.html',
styleUrls: ['./register.component.css']
})
export class TokenComponent implements OnInit {

	token = '';
	tokenStatus = TokenStatus;
	status : TokenStatus;
	errorMessage = '';

	constructor(private authService: AuthService, private route: ActivatedRoute) {

	}

	ngOnInit(): void {
		this.token = this.route.snapshot.queryParamMap.get('token');
		if(this.token){
			this.authService.verifyToken(this.token).subscribe(
			data => {
				this.status = TokenStatus[data.message as keyof TokenStatus];
			}
			,
			err => {
				this.errorMessage = err.error.message;
			}
			);
		}	
	}

	resendToken(): void {
		this.status = TokenStatus.SENDING;
		this.authService.resendToken(this.token).subscribe(
		data => {
			this.status = TokenStatus.SENT;
		}
		,
		err => {
			this.errorMessage = err.error.message;
		}
		);
	}
}

You can have a look at the token verification component section to understand how the enum is being accessed from the component HTML template.

Source Code

https://github.com/JavaChinna/angular-spring-boot-email-integration

Conclusion

That’s all folks. In this article, we have explored how to use enums in angular components and how to convert a string from JSON to enum.

Thank you for reading.

Leave a Reply