Как я могу использовать ngFor для итерации по Typescript Enum в виде массива строк
Я использую Angular2 и Typscript. У меня есть перечисление:
export enum Role {
ServiceAdmin, CompanyAdmin, Foreman, AgentForeman,
CrewMember, AgentCrewMember, Customer
}
Я хочу использовать * ngFor для итерации по перечислению. Каков наилучший способ сделать это? Должен ли я создать трубку? Или есть более простой способ?
Ответы
Ответ 1
Перечисление - это всего лишь объект.
В enum написано что-то вроде этого в JavaScript:
{
0: "ServiceAdmin",
1: "CompanyAdmin",
2: "Foreman",
3: "AgentForeman",
4: "CrewMember",
5: "AgentCrewMember",
6: "Customer",
ServiceAdmin: 0,
CompanyAdmin: 1,
Foreman: 2,
AgentForeman: 3,
CrewMember: 4,
AgentCrewMember: 5,
Customer: 6
}
Таким образом, вы можете перебирать его так (plnkr):
@Component({
...
template: '
<div *ngFor="let item of keys()">
{{ item }}
</div>
'
})
export class YourComponent {
role = Role;
keys() : Array<string> {
var keys = Object.keys(this.role);
return keys.slice(keys.length / 2);
}
}
Или было бы лучше создать пользовательскую трубку:
@Pipe({
name: 'enumToArray'
})
export class EnumToArrayPipe implements PipeTransform {
transform(data: Object) {
const keys = Object.keys(data);
return keys.slice(keys.length / 2);
}
}
пример
Обновить
Typcript 2.4 позволяет членам перечисления содержать инициализаторы строк, такие как:
enum Colors {
Red = "RED",
Green = "GREEN",
Blue = "BLUE",
}
в этом случае вы можете просто вернуть Object.keys(data);
из трубы.
Ответ 2
Область действия шаблона - это экземпляр компонента. Если вы хотите получить доступ к чему-либо за пределами этой области, вам нужно сделать его доступным из экземпляра компонента:
Это также работает, если ключи enum не начинаются с 0
@Pipe({name: 'enumToArray'})
export class EnumToArrayPipe implements PipeTransform {
transform(value) : Object {
return Object.keys(value).filter(e => !isNaN(+e)).map(o => { return {index: +o, name: value[o]}});
}
}
@Component({
...
imports: [EnumsToArrayPipe],
template: '<div *ngFor="let item of roles | enumsToArray">{{item.index}}: {{item.name}}</div>'
})
class MyComponent {
roles = Role;
}
Смотри также fooobar.com/questions/94878/...
Ответ 3
Мне нужно было сделать то же самое, и, возможно, это то, что вы хотели.
Более DRY и его можно использовать с module
тоже.
export enum Role {
ServiceAdmin, CompanyAdmin, Foreman, AgentForeman,
CrewMember, AgentCrewMember, Customer
}
export namespace Role {
export function keys(): Array<string>{
var keys = Object.keys(Role);
return keys.slice(keys.length / 2, keys.length-1);
}
}
вывод объекта перед срезом
{
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"ServiceAdmin",
"CompanyAdmin",
"Foreman",
"AgentForeman",
"CrewMember",
"AgentCrewMember",
"Customer",
"keys"
}
typescript объединяет два объявления, следовательно, keys.lenght-1
и ngFor
:
<div *ngFor="let role of Roles.keys()">{{ role }}</div>
Дополнительная информация:
typescript Объявление слияния
на основе:
TypeScript: Добавить функции в Enum
https://basarat.gitbooks.io/typescript/content/docs/enums.html (в конце главы enums.)
Ответ 4
Вы можете просто использовать канал "keyvalue", представленный в Angular 6.1.
<p *ngFor="let enum of TestEnum | keyvalue">
{{ enum.key }} - {{ enum.value}}
</p>
Смотрите здесь полный пример ->https://stackblitz.com/edit/angular-gujg2e
Ответ 5
После дальнейших исследований и обзора других ответов я теперь могу сформулировать ответ на мой вопрос. Я думаю, что его невозможно просто использовать * ngFor для итерации по перечислению без некоторой поддержки кода в компоненте. Поддержка кода может состоять из кода конструктора, который превращает Enum в какой-то массив или мы можем создать настраиваемый канал, который делает что-то подобное.
Ответ 6
export enum Priority {
LL = 1, // VERY LOW
L = 2, // LOW
N = 3, // NORMAL
U = 4, // HIGH
UU = 5 // VERY HIGH
}
Ваш угловой компонент.ts:
import { Priority } from './../shared/core/config/datas.config';
@Component({
selector: 'app-yourcomponent',
template: '
<ng-container *ngFor="let p of getPriority">
<div> {{p.key}} / {{p.value}} </div>
</ng-container>
'
})
export class YourComponent {
getPriority = this.getENUM(Priority);
getENUM(ENUM:any): string[] {
let myEnum = [];
let objectEnum = Object.keys(ENUM);
const values = objectEnum.slice( 0 , objectEnum.length / 2 );
const keys = objectEnum.slice( objectEnum.length / 2 );
for (let i = 0 ; i < objectEnum.length/2 ; i++ ) {
myEnum.push( { key: keys[i], value: values[i] } );
}
return myEnum;
}
}
Ответ 7
У меня есть перечисление:
export enum FileCategory {
passport = 'Multipass',
agreement = 'Personal agreement',
contract = 'Contract',
photo = 'Self photos',
other = 'Other'
}
В файле компонента ts:
export class MyBestComponent implements OnInit {
fileCategory = FileCategory;
// returns keys of enum
fileKeys(): Array<string> {
const keys = Object.keys(this.fileCategory);
return keys;
}
// returns values of enum
fileVals(): Array<string> {
const keys = Object.keys(this.fileCategory);
return keys.map(el => Object(this.fileCategory)[el]);
}
В шаблоне HTML отобразите эти значения и ключи перечисления:
<a *ngFor="let cat of fileVals()"
(click)="addFileCategory(cat)">{{cat}}</a>
<a *ngFor="let cat of fileKeys()"
(click)="addFileCategory(cat)">{{cat}}</a>
Ответ 8
используя pipeу:
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'enum'
})
export class EnumSelectPipe implements PipeTransform {
transform(value: any): [number, string][] {
return Object.keys(value).filter(t => isNaN(+t)).map(t => [value[t], t]);
}
}
и в шаблоне:
<mat-select formControlName="type" placeholder="Package Type">
<mat-option *ngFor="let pType of PackageTypes | enum" [value]="pType[0]">{{ pType[1] | title}}</mat-option>
</mat-select>
Ответ 9
ES6 поддерживает
export enum E {
a = 'First',
b = 'Second',
c = 'Third'
}
let keyValueArray = Object.keys(E).map(k => ({key: k, value: E[k as any]}));
Ответ 10
В Угловом 7, все еще получая список всех ключей и значений при использовании ключей().
Основываясь на приведенных выше ответах, я использую это для простого ENUM, кажется более чистым и более OO:
export enum CategoryType {
Type1,
Type2,
...,
}
export namespace CategoryType {
export function keys() {
return Object.keys(CategoryType).filter(k => !isNaN(Number(k)));
}
}
затем в шаблоне:
<option *ngFor="let type of types.keys()" [value]="type">{{types[type]}}</option>
Функция становится другой записью в перечислении, но отфильтровывается, как и другие не номера.
Ответ 11
Я рекомендую вам использовать универсальный канал, он будет более гибким и менее избыточным в вашем коде.
Проблема с некоторыми предыдущими предложениями заключается в том, что машинописный текст позволяет вам иметь различные типы перечислений, а не только число/строку.
Например:
export enum NotificationGrouping {
GroupByCreatedAt = "GroupByCreatedAt",
GroupByCreatedByUser = "GroupByCreatedByUser",
GroupByEntity = "GroupByEntity",
GroupByAction = "GroupByAction",
}
Вот мое решение:
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'enumToArray'
})
export class EnumToArrayPipe implements PipeTransform {
transform(value, args: string[]): any {
let result = [];
var keys = Object.keys(value);
var values = Object.values(value);
for (var i = 0; i < keys.length; i++) {
result.push({ key: keys[i], value: values[i] });
}
return result;
//or if you want to order the result:
//return result.sort((a, b) => a.value < b.value ? -1 : 1);
}
}
и HTML будет:
<mat-select [(ngModel)]="groupKey">
<mat-option *ngFor="let group of notificationGrouping | enumToArray"
[value]="group.key">
{{ group.value }}
</mat-option>
</mat-select>
в тс:
public notificationGrouping : NotificationGrouping
Примечание: по-прежнему интересно наблюдать, как люди ставят минус без объяснения причин... Для других, кому может быть интересно это решение, я могу подтвердить, что оно работает правильно.