Use a TypeScript enum as an Angular template variable name with ngTemplateOutlet

2.5k views Asked by At

I have looked at questions like this one. But it doesn't quite answer my question. I want to bind the local variable name to the enum's value like in the following (heavily simplified) example:

In certain-state.component.ts:

export enum CertainState {
    VALID,
    INVALID
}

export class CertainStateComponent {
    // holder for the current state
    public state: CertainState;

    // store the actual enum in the instance of the class so that
    // it is available in the template
    public certainStates: typeof CertainState = CertainState;

    // below is the logic which sets the state
    ...
}

In certain-state.component.html:

<ng-container *ngTemplateOutlet="state_{{state}}"></ng-container>

// obviously this is invalid syntax but I want to demonstrate my intention
<ng-template #state_{{certainStates.VALID}}><span>VALID</span></ng-template>
<ng-template #state_{{certainStates.INVALID}}><span>INVALID</span></ng-template>

EDIT: I think the solution is in the following answer: How to use a typescript enum value in an Angular2 ngSwitch statement. What do you guys think?

2

There are 2 answers

4
Günter Zöchbauer On
public certainStates: typeof CertainState = CertainState;

should be

public certainStates: any = CertainState;

or

public certainStates: {[s: number]: string } = CertainState;
0
Estus Flask On

This is what CertainState enum really is:

(function (CertainState) {
    CertainState[CertainState["VALID"] = 0] = "VALID";
    CertainState[CertainState["INVALID"] = 1] = "INVALID";
})(CertainState = exports.CertainState || (exports.CertainState = {}));

It basically maps keys to indexes and vice versa.

So it should be typed like:

public state: number;
public certainStates: typeof CertainState = CertainState;

And if state name is supposed to be used, it can be looked up on enum:

<ng-container *ngTemplateOutlet="state_{{certainStates[state]}}"></ng-container>
<ng-template #state_{{certainStates[certainStates.VALID]}}><span>VALID</span></ng-template>

Or enum index can be used directly:

<ng-container *ngTemplateOutlet="state_{{state}}"></ng-container>
<ng-template #state_{{certainStates.VALID}}><span>VALID</span></ng-template>

Enums aren't the best choice for cases where a key may be used as a string, because they require extra lookup and don't allow strict typing. As explained here, plain object is generally a better choice for looser typing, and a namespace is good for stricter typing.