ngsubmit ngform form typescript angular angular2-forms

typescript - ngform - Seleccionar basado en enum en Angular2



ngform angular 6 (9)

Tengo esta enumeración (estoy usando TypeScript ):

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

Me gustaría crear una selección en mi formulario , con para cada opción el valor entero de enumeración como valor y el texto de enumeración como etiqueta, de esta manera:

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

Cómo puedo hacer esto ?


A partir de Angular 6.1 y superior, puede usar el KeyValuePipe como se KeyValuePipe a continuación (pegado de documentos angular.io).

Supongo que una enumeración contiene cadenas legibles para los humanos, por supuesto :)

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


Aquí hay una forma muy sencilla para Angular2 v2.0.0. En aras de la integridad, he incluido un ejemplo de establecer un valor predeterminado del country seleccionado a través de formularios reactivos .

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


Con las enumeraciones de cadenas puedes probar esto.

Mi string enum tiene la siguiente definición:

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

y se traduce a js de la siguiente manera:

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

Tengo algunos de estos en mi proyecto, así que creé una pequeña función auxiliar en una biblioteca de servicio compartido:

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

Inicie en su constructor de componentes y vincúlelo a su plantilla de esta manera:

En componente:

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

En plantilla:

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

No olvide agregar el Servicio de servicios a la matriz de proveedores en su app.module.ts para que pueda inyectarlo fácilmente en diferentes componentes.

Soy un novato mecanografiado, así que corríjame si me equivoco o si hay mejores soluciones.


He preferido tener una función de utilidad simple compartida en mi aplicación angular, para convertir la enum en una matriz estándar para crear selecciones:

public countries = enumSelector(CountryCodeEnum);

para llenar una variable en el Componente con:

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

y luego llene mi Material Select como mis antiguos basados ​​en matriz:

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

Gracias por este hilo!


Otra solución similar, que no omite "0" (como "Unset"). Usar filtro (Número) en mi humilde opinión no es un buen enfoque.

@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'']]); }


Otro giro de esta respuesta, pero en realidad esto asigna los valores como números, en lugar de convertirlos en cadenas, lo cual es un error. También funciona con 0 enumeraciones basadas

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


Una solución más si no desea crear una nueva tubería. También puede extraer claves en la propiedad auxiliar y usarla:

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

Demostración: http://plnkr.co/edit/CMFt6Zl7lLYgnHoKKa4E?p=preview

Editar:

si necesita las opciones como números en lugar de cadenas:

  • reemplazar [value] con [ngValue]
  • agregue .map(Number) después de .filter(...)

Esta es la mejor opción que puede aplicar sin tuberías ni código adicional.

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


update2 simplificado creando una matriz

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

actualizar

en lugar de pipes: [KeysPipe]

utilizar

@NgModule({ ... imports: [SharedModule], })

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

original

Uso de la tubería de keys de https://.com/a/35536052/217408

Tuve que modificar un poco la tubería para que funcione correctamente con las enumeraciones (consulte también ¿Cómo obtener los nombres de las entradas de enumeración? )

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

Plunker

Consulte también ¿Cómo iterar claves de objeto usando * ngFor?