typescript - Hur kan jag korrekt binda en enum inom en rullgardinsmeny i Angular 4?


I en rullgardinsmeny har jag använt en Enum-datastruktur (Typescript) för att lagra mina värden. Det verkar dock som att databindningen till objektets kategorifält inte fungerar korrekt och inget är valt som standard. Finns det någon bättre lösning?

export enum CategoryEnum {
      EXAMPLECAT1 = 1,
      EXAMPLECAT2 = 2,
      EXAMPLECAT3 = 3,
      EXAMPLECAT4 = 4
    }

@Component({
  selector: 'category',
  template: `
    <label for="appCategory">Example Category: </label>
    <select class="form-control" id="exampleCategory" required 
            (change)="parseValue($event.target.value)"
            (ngModelChange)="changeSelectedType($event)">
      <option *ngFor="let category of categoryTypes"
              [value]="category">{{category.type}}</option>
    </select>
  `
})

export class CategoryComponent {

  private selectedCategoryType: CategoryEnum
  private categoryTypes;

  constructor(){
    this.categoryTypes = CategoryMapping
  }

  parseValue(value : string) {
    this.selectedCategoryType = AppCategoryEnum[value];
  }

  //Logging: Change Selected Product type callback
  private changeSelectedType(event: any) {
    console.log(event); //object, depends on ngValue
    console.log(this.selectedCategoryType); //object, depends on ngValue
  }
}

Kartläggning av enum-datatypen till etiketter:

export const CategoryMapping = [
  { value: ExampleCategoryEnum.EXAMPLECAT1, type: 'Example 1' },
  { value: ExampleCategoryEnum.EXAMPLECAT2, type: 'Example 2'},
  { value: ExampleCategoryEnum.EXAMPLECAT3, type: 'Example 3'},
  { value: ExampleCategoryEnum.EXAMPLECAT4, type: 'Example 4'}
];

Svar #1

Vi kan förenkla bindningen med ngModel, jag har skapat en annan egenskap att binda med select-elementet och en get-egenskap för att få värdet som CategoryEnum

komponent

  // I have change this to public just for demo
  public get selectedCategoryType():CategoryEnum {
    return this.selectedValue ? this.selectedValue.value: null; 
  }
  private categoryTypes;

  public selectedValue:any;

  constructor() {
    this.categoryTypes = CategoryMapping;
    this.selectedValue = this.categoryTypes[2]; // set default value 
  }

mall

<select class="form-control" id="exampleCategory" required  [(ngModel)]="selectedValue" >
      <option></option>
      <option *ngFor="let category of categoryTypes"
              [ngValue]="category">{{category.type}}</option>
    </select>
<br>

selectedCategoryType :  {{selectedCategoryType | json}}

Du måste använda [ngValue] för alternativ när du vill skicka icke-primitive typer (i ditt fall, objekt) som @trichetriche sa

demo

Svar #2

Skapa först en funktion för att konvertera enum till objektarray

convertEnumToKeyValue(t:any):{value:any,label:any}[]
{
    let keys=Object.keys(t);
    let valueIndex=(keys.length/2);
    let keyArray:{value:any,label:any}[]= [];
    for(let i=0;i<valueIndex;i++)
    {
        keyArray.push({value:keys[i],label:keys[i+valueIndex]});
    }
    return keyArray;
}

then call this like 

enum Colors 
{
   Red=1,
   Green=2,
   Blue=3
}

och slutligen kalla detta

colorTypes= convertEnumToKeyValue(Colors)

och använd nu colorTypes med ngFor i din select