How to use enum typescript value in Angular2 ngSwitch expression

The Typescript variable seems like a natural match for the Angular2 ngSwitch directive. But when I try to use the enumeration in my component template, I get "Can't read property" xxx "from undefined in ...". How can I use enumeration values ​​in my component template?

Note that this is different from how to create html select options based on ALL enum (ngFor) values. This question is about ngSwitch based on the specific value of the enumeration. Although the same approach appears to create an internal enum reference for the class.

+111
angular typescript
Mar 07 '16 at 4:02
source share
9 answers

You can create an enumeration link in your component class (I just changed the starting character to lowercase), and then use this link from the template ( plunker ):

import {Component} from 'angular2/core'; enum CellType {Text, Placeholder} class Cell { constructor(public text: string, public type: CellType) {} } @Component({ selector: 'my-app', template: ` <div [ngSwitch]="cell.type"> <div *ngSwitchCase="cellType.Text"> {{cell.text}} </div> <div *ngSwitchCase="cellType.Placeholder"> Placeholder </div> </div> <button (click)="setType(cellType.Text)">Text</button> <button (click)="setType(cellType.Placeholder)">Placeholder</button> `, }) export default class AppComponent { // Store a reference to the enum cellType = CellType; public cell: Cell; constructor() { this.cell = new Cell("Hello", CellType.Text) } setType(type: CellType) { this.cell.type = type; } } 
+130
Mar 07 '16 at 4:02
source share

You can create a custom decorator that will be added to your component so that it knows about the enumerations.

myenum.enum.ts:

 export enum MyEnum { FirstValue, SecondValue } 

myenumaware.decorator.ts

 import { MyEnum } from './myenum.enum'; export function MyEnumAware(constructor: Function) { constructor.prototype.MyEnum = MyEnum; } 

Listing-aware.component.ts

 import { Component } from '@angular2/core'; import { MyEnum } from './myenum.enum'; import { MyEnumAware } from './myenumaware.decorator'; @Component({ selector: 'enum-aware', template: ` <div [ngSwitch]="myEnumValue"> <div *ngSwitchCase="MyEnum.FirstValue"> First Value </div> <div *ngSwitchCase="MyEnum.SecondValue"> Second Value </div> </div> <button (click)="toggleValue()">Toggle Value</button> `, }) @MyEnumAware // <---------------!!! export default class EnumAwareComponent { myEnumValue: MyEnum = MyEnum.FirstValue; toggleValue() { this.myEnumValue = this.myEnumValue === MyEnum.FirstValue ? MyEnum.SecondValue : MyEnum.FirstValue; } } 
+82
Jan 18 '17 at 22:17
source share

Angular4 - Using Enum in the ngSwitch / ngSwitchCase HTML Template

The solution is here: https://stackoverflow.com/a/416829/

credit: @snorkpete

In your component you have

 enum MyEnum{ First, Second } 

Then, in your component, you enter the Enum type through the 'MyEnum' member and create another member for the enum variable 'myEnumVar':

 export class MyComponent{ MyEnum = MyEnum; myEnumVar:MyEnum = MyEnum.Second ... } 

Now you can use myEnumVar and MyEnum in your .html template. For example, using Enums in ngSwitch:

 <div [ngSwitch]="myEnumVar"> <div *ngSwitchCase="MyEnum.First"><app-first-component></app-first-component></div> <div *ngSwitchCase="MyEnum.Second"><app-second-component></app-second-component></div> <div *ngSwitchDefault>MyEnumVar {{myEnumVar}} is not handled.</div> </div> 
+31
Oct 02 '17 at 23:00
source share

It is simple and works like a charm :) just declare your enum like this and you can use it in your HTML template

  statusEnum: typeof SatusEnum = SatusEnum; 
+15
Mar 03 '18 at 19:53
source share

from rc.6 / final

...

 export enum AdnetNetworkPropSelector { CONTENT, PACKAGE, RESOURCE } <div style="height: 100%"> <div [ngSwitch]="propSelector"> <div *ngSwitchCase="adnetNetworkPropSelector.CONTENT"> <AdnetNetworkPackageContentProps [setAdnetContentModels]="adnetNetworkPackageContent.selectedAdnetContentModel"> </AdnetNetworkPackageContentProps> </div> <div *ngSwitchCase="adnetNetworkPropSelector.PACKAGE"> </div> </div> </div> export class AdnetNetwork { private adnetNetworkPropSelector = AdnetNetworkPropSelector; private propSelector = AdnetNetworkPropSelector.CONTENT; } 
+14
Sep 06 '16 at 18:05
source share

As an alternative to @Eric Lease decorator, which, unfortunately, does not work using --aot (and therefore --prod ), I resorted to using a service that provides all the enumerations of my application. You just need to publicly implement this in every component that requires it, under a simple name, after which you can access the enumerations in your views. For example:

service

 import { Injectable } from '@angular/core'; import { MyEnumType } from './app.enums'; @Injectable() export class EnumsService { MyEnumType = MyEnumType; // ... } 

Do not forget to include it in the list of suppliers of your module.

Component class

 export class MyComponent { constructor(public enums: EnumsService) {} @Input() public someProperty: MyEnumType; // ... } 

HTML component

 <div *ngIf="someProperty === enums.MyEnumType.SomeValue">Match!</div> 
+4
Jul 12 '18 at 13:33
source share

Start by thinking, β€œDo I really want to do this?”

I have no problem with enumeration links directly in HTML, but in some cases there are cleaner alternatives that do not lose type safety. For example, if you choose the approach shown in my other answer, you might have declared TT in your component something like this:

 public TT = { // Enum defines (Horizontal | Vertical) FeatureBoxResponsiveLayout: FeatureBoxResponsiveLayout } 

To show a different layout in your HTML, you must have *ngIf for each layout type, and you can directly access enum in your HTML component:

 *ngIf="(featureBoxResponsiveService.layout | async) == TT.FeatureBoxResponsiveLayout.Horizontal" 

In this example, the service is used to get the current layout, it is started via the asynchronous channel and then compared with our enumeration value. It is rather verbose, confusing and not very interesting to watch. It also exposes the name enum, which in itself may be too verbose.

An alternative that maintains type safety from HTML

Alternatively, you can do the following and declare a more readable function in your .ts component file:

 *ngIf="isResponsiveLayout('Horizontal')" 

Much cleaner! But what if someone 'Horziontal' is mistaken? The whole reason you wanted to use enum in HTML was to be safe, right?

We can still achieve this with keyof and some typewriting magic. This is the function definition:

 isResponsiveLayout(value: keyof typeof FeatureBoxResponsiveLayout) { return FeatureBoxResponsiveLayout[value] == this.featureBoxResponsiveService.layout.value; } 

Note the use of FeatureBoxResponsiveLayout[string] which converts the passed string value to a numeric enumeration value.

This will give an error message with AOT compilation if you use an invalid value.

An argument of type "H4orizontal" cannot be assigned to a parameter of type "Vertical" | "Horizontal"

VSCode is currently not smart enough to emphasize H4orizontal in the HTML editor, but you will get a warning at compile time (using --prod build or --aot switch). It may also be improved in a future update.

+2
Jul 12 '18 at 20:15
source share

If you use the 'typetable reference' approach (from @Carl G) and you use multiple type tables, you can consider this method:

 export default class AppComponent { // Store a reference to the enums (must be public for --AOT to work) public TT = { CellType: CellType, CatType: CatType, DogType: DogType }; ... dog = DogType.GoldenRetriever; 

Then access your HTML file with

 {{ TT.DogType[dog] }} => "GoldenRetriever" 

I prefer this approach, as it makes it clear that you mean typing, and also avoids unnecessary contamination of the component file.

You can also put the global TT somewhere and add enumerations to it as needed (if you want this, you can also create a service as shown in @VincentSels answer). If you have many different tables, this can become cumbersome.

Also, you always rename them in your ad to get a shorter name.

+1
Jun 20 '17 at 20:59 on
source share

My component used a myClassObject type MyClass , which itself used MyEnum . This leads to the same problem described above. Solved this by doing:

 export enum MyEnum { Option1, Option2, Option3 } export class MyClass { myEnum: typeof MyEnum; myEnumField: MyEnum; someOtherField: string; } 

and then use this in the template as

 <div [ngSwitch]="myClassObject.myEnumField"> <div *ngSwitchCase="myClassObject.myEnum.Option1"> Do something for Option1 </div> <div *ngSwitchCase="myClassObject.myEnum.Option2"> Do something for Option2 </div> <div *ngSwitchCase="myClassObject.myEnum.Option3"> Do something for Opiton3 </div> </div> 
0
Apr 17 '19 at 16:04
source share



All Articles