关于typescript:根据Angular2中的枚举进行选择

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=预览


更新

而不是pipes: [KeysPipe]

使用

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的keys管道

我不得不稍微修改一下管道,使它能与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方法。为了完整性起见,我提供了一个通过反应形式设置countryselect的默认值的示例。

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应用程序中共享一个简单的实用功能,将enum转换为标准数组来构建选择:

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及以上版本开始,您可以使用下面的内置KeyValuePipe(粘贴自Angular.io文档)。

我假设枚举包含对人类友好的可读字符串,当然:)

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