wake-up-neo.com

Wie kann ich ngFor verwenden, um TypeScript Enum als ein Array von Zeichenfolgen zu durchlaufen?

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?

33
Rob Gorman

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);
  }
}

Beispiel

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.

44
yurzui

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

11

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.) 

7

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. 

5
Rob Gorman
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;
  }
}
3
Neo_Ryu

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

2
Murolack

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>
2
Pax Beach

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>
1
Elad Tal

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.

0
Cedric Arnould

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.

0
Dovev Hefetz