Ich verwende Angular2 und Typescript. Ich habe eine enum:
export enum Role {
ServiceAdmin, CompanyAdmin, Foreman, AgentForeman,
CrewMember, AgentCrewMember, Customer
}
Ich möchte * ngFor verwenden, um die Aufzählung zu durchlaufen. Was ist der beste Weg, dies zu tun? Muss ich eine Pipe erstellen? Oder gibt es einen einfacheren Weg?
Eine Aufzählung ist nur ein Objekt.
Ihre Enummen sind in JavaScript in etwa so geschrieben:
{
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
}
So können Sie es auf diese Weise wiederholen ( 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);
}
}
Oder wäre besser, eine benutzerdefinierte Pipe zu erstellen:
@Pipe({
name: 'enumToArray'
})
export class EnumToArrayPipe implements PipeTransform {
transform(data: Object) {
const keys = Object.keys(data);
return keys.slice(keys.length / 2);
}
}
Update
Mit TypeScript 2.4 können Enumerationsmitglieder Zeichenfolgeninitialisierer enthalten, z.
enum Colors {
Red = "RED",
Green = "GREEN",
Blue = "BLUE",
}
in diesem Fall können Sie Object.keys(data);
einfach von der Pipe zurückgeben.
Der Bereich der Vorlage ist die Komponenteninstanz. Wenn Sie auf etwas außerhalb dieses Bereichs zugreifen möchten, müssen Sie es ab Ihrer Komponenteninstanz verfügbar machen:
@Pipe({name: 'keys'})
export class KeysPipe implements PipeTransform {
transform(value, args:string[]) : any {
let keys = [];
for (var enumMember in value) {
var isValueProperty = parseInt(enumMember, 10) >= 0
if (isValueProperty) {
keys.Push({key: enumMember, value: value[enumMember]});
// Uncomment if you want log
// console.log("enum member: ", value[enumMember]);
}
}
return keys;
}
}
@Component({
...
pipes: [KeysPipe],
template: `<div *ngFor="let item of roles | keys">{{item}}</div>`
})
class MyComponent {
roles = Role;
}
Siehe auch https://stackoverflow.com/a/35750252/217408
Ich musste dasselbe tun und vielleicht wollten Sie das auch.
Weitere DRY und es kann auch mit module
verwendet werden.
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);
}
}
die Objektausgabe vor dem Slice
{
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"ServiceAdmin",
"CompanyAdmin",
"Foreman",
"AgentForeman",
"CrewMember",
"AgentCrewMember",
"Customer",
"keys"
}
TypeScript führt die beiden Deklarationen zusammen, daher der keys.lenght-1
und die ngFor
:
<div *ngFor="let role of Roles.keys()">{{ role }}</div>
mehr Info:
TypeScript-Deklaration zusammenführen
beyogen auf:
TypeScript: Hinzufügen von Funktionen zu einem Enumhttps://basarat.gitbooks.io/TypeScript/content/docs/enums.html (am Ende des enum Kapitel.)
Nach weiterer Recherche und Überprüfung der anderen Antworten kann ich nun eine Antwort auf meine Frage formulieren. Ich denke, es ist nicht möglich, * ngFor zu verwenden, um eine Enumeration ohne einige Code-Unterstützung in der Komponente zu durchlaufen. Die Code-Unterstützung kann aus Konstruktorcode bestehen, der das Enum in eine Art Array verwandelt, oder wir können eine benutzerdefinierte Pipe erstellen, die etwas Ähnliches tut.
export enum Priority {
LL = 1, // VERY LOW
L = 2, // LOW
N = 3, // NORMAL
U = 4, // HIGH
UU = 5 // VERY HIGH
}
Ihre Winkelkomponente.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;
}
}
Sie können einfach die in Angular 6.1.
<p *ngFor="let enum of TestEnum | keyvalue">
{{ enum.key }} - {{ enum.value}}
</p>
Ein vollständiges Beispiel finden Sie hier -> https://stackblitz.com/edit/angular-gujg2e
Ich habe die enum:
export enum FileCategory {
passport = 'Multipass',
agreement = 'Personal agreement',
contract = 'Contract',
photo = 'Self photos',
other = 'Other'
}
In der Komponente ts-Datei:
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]);
}
Zeigen Sie in der HTML-Vorlage die Werte und Schlüssel dieser Enumeration an:
<a *ngFor="let cat of fileVals()"
(click)="addFileCategory(cat)">{{cat}}</a>
<a *ngFor="let cat of fileKeys()"
(click)="addFileCategory(cat)">{{cat}}</a>
mit rohr:
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]);
}
}
und in der Vorlage:
<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>
Ich empfehle Ihnen, eine generische Pipe zu verwenden, da diese flexibler und in Ihrem Code weniger redundant ist. Das Problem bei einigen früheren Vorschlägen ist, dass Sie mit TypeScript nicht nur eine Zahl/Zeichenfolge, sondern auch eine andere Art von Enumeration haben können.
Zum Beispiel:
export enum NotificationGrouping {
GroupByCreatedAt = "GroupByCreatedAt",
GroupByCreatedByUser = "GroupByCreatedByUser",
GroupByEntity = "GroupByEntity",
GroupByAction = "GroupByAction",
}
Hier ist meine Lösung:
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);
}
}
und der html wird sein:
<mat-select [(ngModel)]="groupKey">
<mat-option *ngFor="let group of notificationGrouping | enumToArray"
[value]="group.key">
{{ group.value }}
</mat-option>
</mat-select>
in ts:
public notificationGrouping : NotificationGrouping
Hinweis: Es ist immer noch interessant zu sehen, wie Leute ohne Erklärung ein Minus setzen ... Für andere, die an dieser Lösung interessiert sein könnten, kann ich bestätigen, dass sie korrekt funktioniert.
In Angular 7 wird immer noch eine Liste aller Schlüssel und Werte angezeigt, wenn Schlüssel () verwendet werden.
Basierend auf den obigen Antworten verwende ich dies für ein einfaches ENUM, scheint sauberer und mehr OO:
export enum CategoryType {
Type1,
Type2,
...,
}
export namespace CategoryType {
export function keys() {
return Object.keys(CategoryType).filter(k => !isNaN(Number(k)));
}
}
dann in der Vorlage:
<option *ngFor="let type of types.keys()" [value]="type">{{types[type]}}</option>
Die Funktion wird zu einem anderen Eintrag in der Aufzählung, wird jedoch wie die anderen Nicht-Nummern herausgefiltert.