Selective Angular Component Rendering with ngSwitch
Tags: angular, typescript
Published: 2020-02-06 07:12:57

---
title: Selective Angular Component Rendering with ngSwitch
published: true
date: 2020-02-06 07:04:15 UTC
tags: Angular, TypeScript
series: Doggo Quest
cover_image: https://pbs.twimg.com/media/EQD9-hkXkAALvD1?format=png
canonical_url: https://killalldefects.com/2020/02/06/selective-angular-component-rendering-with-ngswitch/
---

The post [Selective Angular Component Rendering with ngSwitch](https://killalldefects.com/2020/02/06/selective-angular-component-rendering-with-ngswitch/) appeared first on [Kill All Defects](https://killalldefects.com).

---

Sometimes in Angular you have a collection of items and need to display a different component for different items in the same collection. Thankfully, Angular offers a directive called `ngSwitch` that gives us flexibility in how components render themselves. In this short article I’ll show you an example from my game development project and how I used `ngSwitch` to work around it.

## The Problem

In my particular case I’m [building a text-based adventure game](https://killalldefects.com/2020/02/05/from-mockup-to-angular-material/) in Angular. I have a central region where story text will go, but not all text is equal. Some pieces of text will represent commands the player types in, some will represent story narrative, and some items representing general system status information.

I want these different types of text to be formatted differently, as pictured below:

![Image](https://pbs.twimg.com/media/EQD9-hkXkAALvD1?format=png&name=900x900)

The problem is that when you use `ngFor` to loop over a collection in Angular, the element the `ngFor` directive is on is the one that will be repeated. This makes it harder to represent content dynamically based on the values in the row.

To be more specific, I have an enum representing the different _types_ of story text that are available:

{% gist https://gist.github.com/IntegerMan/f0e498d4ba831577330e429b0a5a7cda %}

The `StoryEntry` class represents the individual lines in the interactive story and looks like this:

{% gist https://gist.github.com/IntegerMan/be8618a9bf243f5a34d3720cabe7e4ac %}

This class is stored in a component as a collection like so:

{% gist https://gist.github.com/IntegerMan/5cd4189fb42598537f0afb3da378cda4 %}

So, now the problem comes in of how we do a `ngFor` over this collection in such a way that different `EntryType` values get rendered with different components.

## The Solution: ngSwitch

The simplest and most maintainable solution I’ve found for this problem is to introduce a new component that takes in the `StoryEntry` object, then _its_ template uses [`ngSwitch`](https://angular.io/api/common/NgSwitch) to conditionally render an additional component based on the `EntryType` of the entry.

`ngSwitch` lets you evaluate some condition inline in your HTML and render the element with a directive matching the switch condition via a `ngSwitchCase` directive. If no condition is matched, the default entry will be included instead if one is defined via the `ngSwitchDefault` directive.

This looks like this:

{% gist https://gist.github.com/IntegerMan/145a39061f56d4034f5cf0f46ca3824d %}

What’s especially noteworthy here is the value in the `ngSwitchCase` directive. We need to be able to reference an enum member by name in our HTML for maintainability. It turns out that in order to do that cleanly in Angular you need to do a little bit of a hack by defining an alias for your enum inside of the component like the following:

{% gist https://gist.github.com/IntegerMan/5f2078dc4ad11c31ab95264fa5a772d9 %}

This added complexity / hack from line 16 is unfortunate, but the best way I know of solving this problem. You could go away from enums entirely and use string values and string comparison, which removes this hack. However, if you did that, you lose the enum member safety that this solution provides.

## End Result

This use of components, `ngSwitch` and using the enum alias gives us a fairly simple approach to conditionally displaying components for some types of entries versus others, which is what we set out to do.

![Image](https://pbs.twimg.com/media/EQD9-hkXkAALvD1?format=png&name=900x900)

Stay tuned as I continue to build out this adventure game over the coming month.