web-dev-qa-db-fra.com

Comment utiliser ngFor pour effectuer une itération sur TypeScript Enum en tant que tableau de chaînes

J'utilise Angular2 et Typescript. J'ai un enum: 

export enum Role {
    ServiceAdmin, CompanyAdmin, Foreman, AgentForeman, 
    CrewMember, AgentCrewMember, Customer
}

Je veux utiliser * ngFor pour parcourir l'énumération. Quelle est la meilleure façon de procéder? Dois-je créer un tuyau? Ou existe-t-il un moyen plus simple?

33
Rob Gorman

Une enum n'est qu'un objet. 

Votre enum est écrit quelque chose comme ceci en 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
}

Donc, vous pouvez le parcourir de cette façon ( 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);
    }
}

Ou serait mieux de créer un tuyau personnalisé:

@Pipe({
  name: 'enumToArray'
})
export class EnumToArrayPipe implements PipeTransform {
  transform(data: Object) {
    const keys = Object.keys(data);
    return keys.slice(keys.length / 2);
  }
}

Exemple

Mettre à jour

TypeScript 2.4 permet aux membres enum de contenir des initialiseurs de chaîne tels que:

enum Colors {
    Red = "RED",
    Green = "GREEN",
    Blue = "BLUE",
}

dans ce cas, vous pouvez simplement renvoyer Object.keys(data); de pipe.

44
yurzui

La portée du modèle est l'instance du composant. Si vous souhaitez accéder à quelque chose en dehors de cette étendue, vous devez le rendre disponible à partir de votre instance de composant:

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

Voir aussi https://stackoverflow.com/a/35750252/217408

11
Günter Zöchbauer

J'avais besoin de faire la même chose et c'est peut-être ce que tu voulais.
Plus DRY et il peut également être utilisé avec 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);
  }
}

la sortie de l'objet avant la tranche

{
    "1",
    "2",
    "3",
    "4",
    "5",
    "6",
    "7",
    "ServiceAdmin",
    "CompanyAdmin",
    "Foreman",
    "AgentForeman",
    "CrewMember",
    "AgentCrewMember",
    "Customer",
    "keys"
}

TypeScript fusionne les deux déclarations d'où le keys.lenght-1 

et la ngFor:

<div *ngFor="let role of Roles.keys()">{{ role }}</div>

plus d'informations:
Déclaration TypeScript fusionnant

basé sur:
TypeScript: Ajout de fonctions à un Enumhttps://basarat.gitbooks.io/TypeScript/content/docs/enums.html (à la fin du enums chapitre.) 

7

Après des recherches plus approfondies et une revue des autres réponses, je peux maintenant formuler une réponse à ma question. Je pense qu'il n'est pas possible d'utiliser simplement * ngFor pour effectuer une itération sur une enum sans prise en charge de code dans le composant. La prise en charge du code peut consister en un code constructeur qui transforme l’énum en une sorte de tableau ou nous pouvons créer un canal personnalisé faisant quelque chose de similaire. 

5
Rob Gorman
export enum Priority {
  LL = 1,   // VERY LOW
  L = 2,    // LOW
  N = 3,    // NORMAL
  U = 4,    // HIGH
  UU = 5    // VERY HIGH
}

Vos composantes angulaires:

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

J'ai l'énum:

export enum FileCategory {
  passport = 'Multipass',
  agreement = 'Personal agreement',
  contract = 'Contract',
  photo = 'Self photos',
  other = 'Other'
}

Dans le fichier composant 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]);
  }

Dans le modèle HTML, affichez les valeurs et les clés de cet enum:

  <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

Dans Angular 7, vous obtenez toujours une liste de toutes les clés et valeurs lorsque vous utilisez keys ().

Sur la base des réponses ci-dessus, je l’utilise pour un simple ENUM, semble plus propre et plus orienté objet:

export enum CategoryType {
    Type1,
    Type2,
    ...,
}

export namespace CategoryType {
    export function keys() {
        return Object.keys(CategoryType).filter(k => !isNaN(Number(k)));
    }
}

puis dans le modèle:

<option *ngFor="let type of types.keys()" [value]="type">{{types[type]}}</option>

La fonction devient une autre entrée dans l'énumération, mais est filtrée comme les autres non-nombres.

0
Dovev Hefetz