Typescript枚举似乎与Angular2的ngSwitch指令完全匹配。但是当我尝试在我的组件模板中使用枚举时,我得到了#34;无法读取属性' xxx'未定义的..."。如何在组件模板中使用枚举值?
请注意,这与根据枚举的所有值(ngFor)创建html选择选项的方法不同。这个问题是关于ngSwitch基于枚举的特定值。虽然出现了创建枚举的类内部引用的相同方法。
答案 0 :(得分:138)
您可以在组件类中创建对枚举的引用(我只是将初始字符更改为小写),然后使用模板中的引用(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;
}
}
答案 1 :(得分:83)
您可以创建自定义装饰器以添加到组件中,以使其了解枚举。
export enum MyEnum {
FirstValue,
SecondValue
}
import { MyEnum } from './myenum.enum';
export function MyEnumAware(constructor: Function) {
constructor.prototype.MyEnum = MyEnum;
}
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;
}
}
答案 2 :(得分:32)
Angular4 - 在HTML模板中使用枚举ngSwitch / ngSwitchCase
此处的解决方案:https://stackoverflow.com/a/42464835/802196
信用:@snorkpete在您的组件中,您有
enum MyEnum{
First,
Second
}
然后在您的组件中,您通过会员&#39; MyEnum&#39;引入Enum类型,并为您的枚举变量&#39; myEnumVar&#39;创建另一个成员。 :
export class MyComponent{
MyEnum = MyEnum;
myEnumVar:MyEnum = MyEnum.Second
...
}
您现在可以在.html模板中使用myEnumVar和MyEnum。例如,在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>
答案 3 :(得分:15)
这很简单,就像一个魅力:) 只需声明你的枚举,你可以在HTML模板上使用它
statusEnum: typeof SatusEnum = SatusEnum;
答案 4 :(得分:14)
截至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;
}
答案 5 :(得分:6)
作为@Eric Lease的装饰器的一种替代方法,不幸的是,该装饰器无法使用namespace AdMobTestProject
{
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
}
public class AdMobView : ContentView
{
public AdMobView()
{
}
}
}
(因此,<div id="register-modal" class="modal fade" tabindex="-1" role="dialog" aria- hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" aria-label="Close" (click)="closeModal()">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title" style="text-align:center">Register</h4>
</div>
<form name="registerForm" #registerForm="ngForm" (ngSubmit)=" !errordata.isErrorData && registerForm.valid && registerManager()">
<div class="modal-body">
<div class="container-fluid">
<div class="row">
<div class="col-md-12">
<div class="box">
<div class="box-body">
<div class="box box-solid box-primary">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label class="col-sm-3 control-label">First Name
<span style="color:red">*</span>
</label>
<div class="col-sm-9">
<input type="text" placeholder="First Name" [(ngModel)]="registerData.firstName" name="firstName" class="form-control" pattern="[a-zA-Z/s ]*" maxlength="20" #firstName="ngModel" required>
<div *ngIf="firstName.valid || firstName.touched || registerForm.submitted">
<div class="error-msg" *ngIf="firstName.errors && firstName.errors.required" class="text-danger">
First Name is required.
</div>
<div class="error-msg" *ngIf="firstName.errors && firstName.errors.pattern" class="text-danger">
Enter Valid First Name.
</div>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label class="col-sm-3 control-label">Last Name
<span style="color:red">*</span>
</label>
<div class="col-sm-9">
<input type="text" placeholder="Last Name" [(ngModel)]="registerData.lastName" name="lastName" class="form-control" pattern="[a-zA-Z/s ]*" maxlength="20" #lastName="ngModel" required>
<div *ngIf="lastName.valid || lastName.touched || registerForm.submitted">
<div class="error-msg" *ngIf="lastName.errors && lastName.errors.required" class="text-danger">
Last Name is required.
</div>
<div class="error-msg" *ngIf="lastName.errors && lastName.errors.pattern" class="text-danger">
Enter Valid Name.
</div>
</div>
</div>
</div>
</div>
</div>
<br>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label class="col-sm-3 control-label">Email
<span style="color:red">*</span>
</label>
<div class="col-sm-9">
<input type="email" placeholder="Email" [(ngModel)]="registerData.email" name="email" class="form-control" #email="ngModel" (blur)="checkEmail(registerData.email)" required pattern="[_a-z0-9]+(\.[_a-z0-9]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})">
<div *ngIf="email.valid || email.touched || registerForm.submitted">
<div class="error-msg" *ngIf="email.errors && email.errors.required" class="text-danger">
Email is required.
</div>
<div class="error-msg" *ngIf="email.errors && email.errors.pattern" class="text-danger">
Enter Valid Eamil.
</div>
<div *ngIf="errordata.isErrorData" class="text-danger"> {{ errordata.errorMessage }}</div>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label class="col-sm-3 control-label">Password
<span style="color:red">*</span>
</label>
<div class="col-sm-9">
<input type="password" placeholder="Password" [(ngModel)]="registerData.password" name="password" class="form-control" maxlength="20" #password="ngModel" required>
<div *ngIf="password.valid || password.touched || registerForm.submitted">
<div class="error-msg" *ngIf="password.errors && password.errors.required" class="text-danger">
Password is required.
</div>
<div class="error-msg" *ngIf="password.errors && password.errors.pattern" class="text-danger">
Enter Valid Password.
</div>
</div>
</div>
</div>
</div>
</div>
<br>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label class="col-sm-3 control-label">Date Of Birth
<span style="color:red">*</span>
</label>
<div class="col-sm-9">
<input type="date" placeholder="DOB" [(ngModel)]="registerData.dateOfBirth" name="dob" class="form-control" #dob="ngModel" required>
<div *ngIf="dob.valid || dob.touched || registerForm.submitted">
<div class="error-msg" *ngIf="dob.errors && dob.errors.required" class="text-danger">
dob is required.
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<div class="pull-right">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
<div class="pull-left">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
</div>
</div>
</form>
</div>
</div>
</div>
)构建无法工作,我求助于使用公开我所有应用程序枚举的服务。只需以简单的名称将其公开地注入到需要它的每个组件中,之后您就可以访问视图中的枚举了。例如:
服务
--aot
请不要忘记将其包括在模块的提供者列表中。
组件类
--prod
组件html
import { Injectable } from '@angular/core';
import { MyEnumType } from './app.enums';
@Injectable()
export class EnumsService {
MyEnumType = MyEnumType;
// ...
}
答案 6 :(得分:2)
我在HTML中直接引用枚举没有问题,但是在某些情况下,还有一些更干净的替代方法不会丢失类型安全性。 例如,如果您选择我的其他答案中所示的方法,则可能已在组件中声明了TT,如下所示:
public TT =
{
// Enum defines (Horizontal | Vertical)
FeatureBoxResponsiveLayout: FeatureBoxResponsiveLayout
}
要在HTML中显示不同的布局,您需要为每种布局类型使用*ngIf
,并且可以直接引用组件HTML中的枚举:
*ngIf="(featureBoxResponsiveService.layout | async) == TT.FeatureBoxResponsiveLayout.Horizontal"
此示例使用服务获取当前布局,通过异步管道运行它,然后将其与我们的枚举值进行比较。它很冗长,令人费解,看起来也没有太多乐趣。它还公开了枚举的名称,该名称本身可能过于冗长。
或者,您可以执行以下操作,并在组件的.ts文件中声明一个更具可读性的函数:
*ngIf="isResponsiveLayout('Horizontal')"
更清洁!但是,如果有人错误输入'Horziontal'
怎么办?您想在HTML中使用枚举的全部原因是类型安全的吗?
我们仍然可以使用keyof和一些打字稿魔术来实现这一目标。这是函数的定义:
isResponsiveLayout(value: keyof typeof FeatureBoxResponsiveLayout)
{
return FeatureBoxResponsiveLayout[value] == this.featureBoxResponsiveService.layout.value;
}
请注意FeatureBoxResponsiveLayout[string]
的用法,其中converts字符串值传递给枚举的数值。
如果您使用无效的值,这将给出一条错误消息,提示AOT编译。
不能将类型“ H4orizontal”的参数分配给类型“垂直”的参数。 “水平”
当前,VSCode不够智能,无法在HTML编辑器中对H4orizontal
下划线,但是您会在编译时收到警告(使用--prod build或--aot开关)。将来的更新中可能还会对此进行改进。
答案 7 :(得分:1)
如果使用&#39; typetable参考&#39;方法(来自@Carl G)并且您使用多种类型表,您可能需要考虑这种方式:
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;
然后使用
访问您的html文件{{ TT.DogType[dog] }} => "GoldenRetriever"
我赞成这种方法,因为它清楚地表明您指的是类型表,并且还避免了对组件文件造成不必要的污染。
您还可以在某处放置一个全局TT
,并根据需要为其添加枚举(如果您需要,您也可以按@VincentSels答案显示服务)。如果你有很多类型表,这可能会变得很麻烦。
此外,您总是在声明中重命名它们以获得更短的名称。
答案 8 :(得分:0)
我的组件使用了类型为myClassObject
的对象MyClass
,该对象本身正在使用MyEnum
。这导致上述相同的问题。通过执行以下操作解决了该问题:
export enum MyEnum {
Option1,
Option2,
Option3
}
export class MyClass {
myEnum: typeof MyEnum;
myEnumField: MyEnum;
someOtherField: string;
}
,然后在模板中将其用作
<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>