Select based on enum in Angular2
我有这个枚举(我使用的是typescript):
1 2 3 4 | export enum CountryCodeEnum { France = 1, Belgium = 2 } |
我想在表单中构建一个select,其中每个选项的枚举整数值为value,枚举文本为label,如下所示:
1 2 3 4 | <select> <option value="1">France</option> <option value="2">Belgium</option> </select> |
我该怎么做?
如果不想创建新管道,还需要一个解决方案。您还可以将密钥提取到helper属性中并使用它:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | @Component({ selector: 'my-app', providers: [], template: ` <select> <option *ngFor="let key of keys" [value]="key" [label]="countries[key]"></option> </select> `, directives: [] }) export class App { countries = CountryCodeEnum constructor() { this.keys = Object.keys(this.countries).filter(Number) } } |
演示:http://plnkr.co/edit/cmft6zl7llygnokka4e?P=预览
更新
而不是
使用
1 2 3 4 5 | @NgModule({ declarations: [KeysPipe], exports: [KeysPipe], } export class SharedModule{} |
1 2 3 4 | @NgModule({ ... imports: [SharedModule], }) |
起初的
使用来自https://stackoverflow.com/a/35536052/217408的
我不得不稍微修改一下管道,使它能与Enums一起正常工作。(另请参见如何获取typescript枚举项的名称?)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | @Pipe({name: 'keys'}) export class KeysPipe implements PipeTransform { transform(value, args:string[]) : any { let keys = []; for (var enumMember in value) { if (!isNaN(parseInt(enumMember, 10))) { keys.push({key: enumMember, value: value[enumMember]}); // Uncomment if you want log // console.log("enum member:", value[enumMember]); } } return keys; } } @Component({ ... pipes: [KeysPipe], template: ` <select> <option *ngFor="let item of countries | keys" [value]="item.key">{{item.value}}</option> </select> ` }) class MyComponent { countries = CountryCodeEnum; } |
柱塞
另请参见如何将*ngfor用于对象?
这里是一个非常简单的Angular2 v2.0.0方法。为了完整性起见,我提供了一个通过反应形式设置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | @Component({ selector: 'my-app', providers: [], template: ` <select id="country" formControlName="country"> <option *ngFor="let key of keys" [value]="key">{{countries[key]}}</option> </select> `, directives: [] }) export class App { keys: any[]; countries = CountryCodeEnum; constructor(private fb: FormBuilder) { this.keys = Object.keys(this.countries).filter(Number); this.country = CountryCodeEnum.Belgium; //Default the value } } |
另一个类似的解决方案,不省略"0"(如"unset")。使用过滤器(数字)IMHO不是一个好方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | @Component({ selector: 'my-app', providers: [], template: ` <select> <option *ngFor="let key of keys" [value]="key" [label]="countries[key]"></option> </select>`, directives: [] }) export class App { countries = CountryCodeEnum; constructor() { this.keys = Object.keys(this.countries).filter(f => !isNaN(Number(f))); } } // ** NOTE: This enum contains 0 index ** export enum CountryCodeEnum { Unset = 0, US = 1, EU = 2 } |
我更喜欢在我的Angular应用程序中共享一个简单的实用功能,将
1 2 3 4 | export function enumSelector(definition) { return Object.keys(definition) .map(key => ({ value: definition[key], title: key })); } |
要在组件中填充变量,请执行以下操作:
1 | public countries = enumSelector(CountryCodeEnum); |
然后填充我的材料,选择作为我以前的基于阵列的材料:
1 2 3 4 5 | <md-select placeholder="Country" [(ngModel)]="country" name="country"> <md-option *ngFor="let c of countries" [value]="c.value"> {{ c.title }} </md-option> </md-select> |
谢谢你的线!
从Angular 6.1及以上版本开始,您可以使用下面的内置
我假设枚举包含对人类友好的可读字符串,当然:)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | @Component({ selector: 'keyvalue-pipe', template: `<span> <p> Object </p> {{item.key}}:{{item.value}} <p> Map </p> {{item.key}}:{{item.value}} </span>` }) export class KeyValuePipeComponent { object: {[key: number]: string} = {2: 'foo', 1: 'bar'}; map = new Map([[2, 'foo'], [1, 'bar']]); } |
这个答案的另一个副产品,但它实际上将值映射为数字,而不是将它们转换为字符串,这是一个bug。它也适用于基于0的枚举
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | @Component({ selector: 'my-app', providers: [], template: ` <select> <option *ngFor="let key of keys" [value]="key" [label]="countries[key]"></option> </select>`, directives: [] }) export class App { countries = CountryCodeEnum; constructor() { this.keys = Object.keys(this.countries) .filter(f => !isNaN(Number(f))) .map(k => parseInt(k));; } } |
使用字符串枚举可以尝试此操作。
我的字符串枚举具有以下定义:
1 2 3 4 | enum StatusEnum { Published = 'published', Draft = 'draft' } |
并按以下方式转换为JS:
1 2 3 4 5 6 | { Published:"published", published:"Published", Draft:"draft", draft:"Draft" } |
我在我的项目中有一些这样在共享服务库中创建了小助手函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | @Injectable() export class UtilsService { stringEnumToKeyValue(stringEnum) { const keyValue = []; const keys = Object.keys(stringEnum).filter((value, index) => { return !(index % 2); }); for (const k of keys) { keyValue.push({key: k, value: stringEnum[k]}); } return keyValue; } } |
在组件构造函数中初始化并将其绑定到模板,如下所示:
组件中:
1 2 3 4 5 | statusSelect; constructor(private utils: UtilsService) { this.statusSelect = this.utils.stringEnumToKeyValue(StatusEnum); } |
模板中:
1 2 3 | <option *ngFor="let status of statusSelect" [value]="status.value"> {{status.key}} </option> |
别忘了在app.module.ts中将utilsservice添加到provider数组中,这样您就可以轻松地将它注入到不同的组件中。
我是个打字新手,所以如果我错了或者有更好的解决方案,请纠正我。
这是不需要任何管道或额外代码就可以应用的最佳选项。
16