web-dev-qa-db-fra.com

Sélectionnez basé sur enum dans Angular2

J'ai cette énumération (j'utilise TypeScript):

export enum CountryCodeEnum {
    France = 1,
    Belgium = 2
}

Je voudrais construire un select dans mon formulaire, avec pour chaque option la valeur entière enum en tant que valeur et le texte enum en tant qu'étiquette, comme ça :

<select>
     <option value="1">France</option>
     <option value="2">Belgium</option>
</select>

Comment puis-je faire ceci ?

62
AdrienTorris

update2 simplifié par la création d'un tableau

@Pipe({name: 'enumToArray'})
export class EnumToArrayPipe implements PipeTransform {
  transform(value) : Object {
    return Object.keys(value).filter(e => !isNaN(+e)).map(e => {return {[e]: value[e]}})
  }
}

@Component({
  ...
  imports: [EnumsToArrayPipe],
  template: `<div *ngFor="let item of roles | enumsToArray; let idx=index">{{idx}}: {{item}}</div>`
})
class MyComponent {
  roles = Role;
}

mettre à jour

au lieu de pipes: [KeysPipe]

utilisation

@NgModule({
  declarations: [KeysPipe],
  exports: [KeysPipe],
}
export class SharedModule{}
@NgModule({
  ...
  imports: [SharedModule],
})

original

Utilisation du canal keys de https://stackoverflow.com/a/35536052/217408

Je devais modifier un peu le tuyau pour le faire fonctionner correctement avec enums (voir aussi Comment obtenir les noms des entrées enum? )

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

Plunker

Voir aussi Comment itérer les clés d'objet avec * ngFor?

44

Une autre solution si vous ne voulez pas créer un nouveau tuyau. Vous pouvez également extraire des clés dans la propriété helper et l’utiliser:

@Component({
  selector: 'my-app',
  providers: [],
  template: `
    <div>
      <select>
        <option *ngFor="let key of keys" [value]="key" [label]="countries[key]"></option>
      </select>
    </div>
  `,
  directives: []
})
export class App {

  countries = CountryCodeEnum

  constructor() {
    this.keys = Object.keys(this.countries).filter(Number)
  }
}

Démo: http://plnkr.co/edit/CMFt6Zl7lLYgnHoKKa4E?p=preview

48
dfsq

Voici un moyen très simple pour Angular2 v2.0.0. Par souci d’exhaustivité, j’ai inclus un exemple de définition d’une valeur par défaut de country select via formes réactives .

@Component({
  selector: 'my-app',
  providers: [],
  template: `
    <div>
      <select id="country" formControlName="country">
        <option *ngFor="let key of keys" [value]="key">{{countries[key]}}</option>
      </select>
    </div>
  `,
  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
  }
}
20
rynop

J'ai préféré disposer d'une fonction utilitaire simple partagée sur mon Angular App, pour convertir la enum en un tableau standard afin de générer la sélection:

export function enumSelector(definition) {
  return Object.keys(definition)
    .map(key => ({ value: definition[key], title: key }));
}

remplir une variable dans le composant avec:

public countries = enumSelector(CountryCodeEnum);

puis remplissez ma sélection de matériaux en tant qu'anciennes bases basées sur un tableau:

<md-select placeholder="Country" [(ngModel)]="country" name="country">
  <md-option *ngFor="let c of countries" [value]="c.value">
    {{ c.title }}
  </md-option>
</md-select>

Merci pour ce fil!

9
Mateo Tibaquira

Une autre solution similaire, qui n'omette pas "0" (comme "Unset"). Utilisation du filtre (nombre) IMHO n'est pas une bonne approche.

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

À partir de Angular 6.1 et supérieur, vous pouvez utiliser le KeyValuePipe intégré comme ci-dessous (collé à partir de documents angular.io).

Je suppose qu’une énumération contient bien sûr des chaînes lisibles par des êtres humains :)

@Component({
  selector: 'keyvalue-pipe',
  template: `<span>
    <p>Object</p>
    <div *ngFor="let item of object | keyvalue">
      {{item.key}}:{{item.value}}
    </div>
    <p>Map</p>
    <div *ngFor="let item of map | keyvalue">
      {{item.key}}:{{item.value}}
    </div>
  </span>`
})
export class KeyValuePipeComponent {
  object: {[key: number]: string} = {2: 'foo', 1: 'bar'};
  map = new Map([[2, 'foo'], [1, 'bar']]);
}
3
Samuel R

Une autre conséquence de cette réponse, mais cela mappe en réalité les valeurs sous forme de nombres, au lieu de les convertir en chaînes, ce qui est un bogue. Cela fonctionne aussi avec 0 enums basés

@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));;
  }
}
2
johnny 5

Avec des énumérations de chaîne, vous pouvez essayer ceci.

Mon enum string a la définition suivante:

    enum StatusEnum {
        Published = <any> 'published',
        Draft = <any> 'draft'
    }

et traduit en js de la manière suivante:

   {
       Published: "published", 
       published: "Published", 
       Draft: "draft", 
       draft: "Draft"
   }

J'ai quelques-uns de ceux-ci dans mon projet, donc créé une petite fonction d'assistance dans une bibliothèque de services partagés:

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

Init dans le constructeur de votre composant et le lier à votre modèle comme ceci:

En composant:

    statusSelect;

    constructor(private utils: UtilsService) {
        this.statusSelect = this.utils.stringEnumToKeyValue(StatusEnum);
    }

Dans le modèle:

    <option *ngFor="let status of statusSelect" [value]="status.value">
        {{status.key}}
    </option>

N'oubliez pas d'ajouter UtilsService au tableau de fournisseurs dans votre app.module.ts afin de pouvoir l'injecter facilement dans différents composants.

Je suis un débutant en TypeScript, donc corrigez-moi si je me trompe ou s'il existe de meilleures solutions.

1
Christopher

C'est la meilleure option que vous pouvez appliquer sans aucun tuyau ni code supplémentaire.

import { Component } from '@angular/core';

 enum AgentStatus {
    available =1 ,
    busy = 2,
    away = 3,
    offline = 0
}


@Component({
  selector: 'my-app',
  template: `
  <h1>Choose Value</h1>

  <select (change)="parseValue($event.target.value)">
    <option>--select--</option>
    <option *ngFor="let name of options"
        [value]="name">{{name}}</option>
  </select>

  <h1 [hidden]="myValue == null">
    You entered {{AgentStatus[myValue]}}

  </h1>`
})
export class AppComponent { 


  options : string[];
  myValue: AgentStatus;
  AgentStatus : typeof AgentStatus = AgentStatus;

  ngOnInit() {
    var x = AgentStatus;
    var options = Object.keys(AgentStatus);
    this.options = options.slice(options.length / 2);
  }

  parseValue(value : string) {
    this.myValue = AgentStatus[value];

  }
}
1
Nimish goel