Как использовать значение перечисления typescript в инструкции Angular2 ngSwitch



машинопись перечисление, кажется, естественным образом совпадает с директивой ngSwitch Angular2 по. Но когда я пытаюсь использовать перечисление в шаблоне моего компонента, я получаю "не могу прочитать свойство 'xxx' undefined in ...". Как я могу использовать значения перечисления в моем шаблоне компонента?



обратите внимание, что это отличается от того, как создать параметры выбора html на основе всех значений перечисления (ngFor). Этот вопрос касается ngSwitch, основанного на определенном значении перечисления. Хотя то же самое появляется подход создания класса-внутренняя ссылка на перечисление.

641   8  

8 ответов:

вы можете создать ссылку на перечисление в своем классе компонентов (я просто изменил начальный символ на нижний регистр), а затем использовать эту ссылку из шаблона (plunker):

import {Component} from 'angular2/core';

enum CellType {Text, Placeholder}
class Cell {
  constructor(public text: string, public type: CellType) {}
}
@Component({
  selector: 'my-app',
  template: `
    <div [ngSwitch]="cell.type">
      <div *ngSwitchCase="cellType.Text">
        {{cell.text}}
      </div>
      <div *ngSwitchCase="cellType.Placeholder">
        Placeholder
      </div>
    </div>
    <button (click)="setType(cellType.Text)">Text</button>
    <button (click)="setType(cellType.Placeholder)">Placeholder</button>
  `,
})
export default class AppComponent {

  // Store a reference to the enum
  cellType = CellType;
  public cell: Cell;

  constructor() {
    this.cell = new Cell("Hello", CellType.Text)
  }

  setType(type: CellType) {
    this.cell.type = type;
  }
}

вы можете создать пользовательский декоратор для добавления в свой компонент, чтобы он знал о перечислениях.

myenum.перечисление.ТС:

export enum MyEnum {
    FirstValue,
    SecondValue
}

myenumaware.оформитель.ТС

import { MyEnum } from './myenum.enum';

export function MyEnumAware(constructor: Function) {
    constructor.prototype.MyEnum = MyEnum;
}

enum-aware.деталь.ТС

import { Component } from '@angular2/core';
import { MyEnum } from './myenum.enum';
import { MyEnumAware } from './myenumaware.decorator';

@Component({
  selector: 'enum-aware',
  template: `
    <div [ngSwitch]="myEnumValue">
      <div *ngSwitchCase="MyEnum.FirstValue">
        First Value
      </div>
      <div *ngSwitchCase="MyEnum.SecondValue">
        Second Value
      </div>
    </div>
    <button (click)="toggleValue()">Toggle Value</button>
  `,
})
@MyEnumAware // <---------------!!!
export default class EnumAwareComponent {
  myEnumValue: MyEnum = MyEnum.FirstValue;

  toggleValue() {
    this.myEnumValue = this.myEnumValue === MyEnum.FirstValue
        ? MyEnum.SecondValue : MyEnum.FirstValue;
  }
}

Angular4-использование перечисления в HTML шаблоне ngSwitch / ngSwitchCase

решение здесь:https://stackoverflow.com/a/42464835/802196

кредит: @snorkpete

в вашем компоненте, у вас есть

enum MyEnum{
  First,
  Second
}

затем в вашем компоненте вы вводите тип перечисления через член "MyEnum" и создаете другой член для своей переменной перечисления "myEnumVar":

export class MyComponent{
  MyEnum = MyEnum;
  myEnumVar:MyEnum = MyEnum.Second
  ...
}

Теперь вы можете использовать myEnumVar и MyEnum в вашем .формат html шаблон. Например, используя перечисления в ngSwitch:

<div [ngSwitch]="myEnumVar">
  <div *ngSwitchCase="MyEnum.First"><app-first-component></app-first-component></div>
  <div *ngSwitchCase="MyEnum.Second"><app-second-component></app-second-component></div>
  <div *ngSwitchDefault>MyEnumVar {{myEnumVar}} is not handled.</div>
</div>

по состоянию на rc.6 / заключительный

...

export enum AdnetNetworkPropSelector {
    CONTENT,
    PACKAGE,
    RESOURCE
}

<div style="height: 100%">
          <div [ngSwitch]="propSelector">
                 <div *ngSwitchCase="adnetNetworkPropSelector.CONTENT">
                      <AdnetNetworkPackageContentProps [setAdnetContentModels]="adnetNetworkPackageContent.selectedAdnetContentModel">
                                    </AdnetNetworkPackageContentProps>
                  </div>
                 <div *ngSwitchCase="adnetNetworkPropSelector.PACKAGE">
                </div>
            </div>              
        </div>


export class AdnetNetwork {       
    private adnetNetworkPropSelector = AdnetNetworkPropSelector;
    private propSelector = AdnetNetworkPropSelector.CONTENT;
}

Это просто и работает как шарм :) просто объявите свое перечисление так, и вы можете использовать его на HTML-шаблоне

  statusEnum: typeof SatusEnum = SatusEnum;

в качестве альтернативы декоратору @Eric Lease, который, к сожалению, не работает с помощью --aot (и таким образом --prod) строит, я прибегал к использованию службы, которая предоставляет все перечисления моего приложения. Просто нужно публично ввести это в каждый компонент, который этого требует, под простым именем, после чего вы можете получить доступ к перечислениям в своих представлениях. Например:

сервис

import { Injectable } from '@angular/core';
import { MyEnumType } from './app.enums';

@Injectable()
export class EnumsService {
  MyEnumType = MyEnumType;
  // ...
}

Не забудьте включить его в провайдера вашего модуля список.

компонент класс

export class MyComponent {
  constructor(public enums: EnumsService) {}
  @Input() public someProperty: MyEnumType;

  // ...
}

компонент html

<div *ngIf="someProperty === enums.MyEnumType.SomeValue">Some property has some value!</div>

Если вы используете подход "typetable reference" (от @Carl G) и используете несколько таблиц типов, вы можете рассмотреть этот способ:

export default class AppComponent {

  // Store a reference to the enums (must be public for --AOT to work)
  public TT = { 
       CellType: CellType, 
       CatType: CatType, 
       DogType: DogType 
  };

  ...

  dog = DogType.GoldenRetriever; 

затем доступ в ваш HTML-файл с

{{ TT.DogType[dog] }}   => "GoldenRetriever"

Я поддерживаю этот подход, поскольку он ясно дает понять, что вы имеете в виду typetable, а также позволяет избежать ненужного загрязнения вашего файла компонента.

вы также можете поставить глобальный TT где-то и добавить перечисления к нему по мере необходимости (если вы хотите этого вы также можете сделайте услугу, как показано в ответе @VincentSels). Если у вас есть много много таблиц типов это может стать громоздким.

также вы всегда переименовать их в своей декларации, чтобы получить короткое имя.

начните с рассмотрения 'Do I действительно хотите это сделать?-

у меня нет проблем со ссылкой на перечисления непосредственно в HTML, но в некоторых случаях есть более чистые альтернативы, которые не теряют типобезопасность. Например, если вы выберете подход, показанный в моем другом ответе, вы можете объявить TT в своем компоненте примерно так:

public TT = 
{
    // Enum defines (Horizontal | Vertical)
    FeatureBoxResponsiveLayout: FeatureBoxResponsiveLayout   
}

чтобы показать другой макет в вашем HTML, у вас будет *ngIf для каждого типа макета, и вы можете обратиться непосредственно к перечислению в HTML вашего компонента:

*ngIf="(featureBoxResponsiveService.layout | async) == TT.FeatureBoxResponsiveLayout.Horizontal"

в этом примере используется служба для получения текущего макета, запускает его через асинхронный канал, а затем сравнивает его с нашим значением перечисления. Это довольно многословно, запутанно и не очень весело смотреть. Он также раскрывает название перечисления, которое само по себе может быть слишком многословным.

альтернатива, которая сохраняет безопасность типа от HTML

в качестве альтернативы вы можете сделать следующее, и объявить более читаемый функция в вашем компоненте .файл ТС :

*ngIf="isResponsiveLayout('Horizontal')"

намного чище! Но что делать, если кто-то вводит 'Horziontal' по ошибке? Вся причина, по которой вы хотели использовать перечисление в HTML, должна была быть типобезопасной, верно?

мы все еще можем достичь этого с keyof и немного машинописной магии. Это определение функции:

isResponsiveLayout(value: keyof typeof FeatureBoxResponsiveLayout)
{
    return FeatureBoxResponsiveLayout[value] == this.featureBoxResponsiveService.layout.value;
}

обратите внимание на использование FeatureBoxResponsiveLayout[string], который преобразование строковое значение, переданное в числовое значение перечисление.

это даст сообщение об ошибке с AOT-компиляции, если вы используете недопустимое значение.

аргумент типа '" H4orizontal "'не присваивается параметру типа '"Vertical" | "Horizontal"

В настоящее время VSCode недостаточно умен, чтобы подчеркнуть H4orizontal в Редакторе HTML, но вы получите предупреждение во время компиляции (с --prod build или --AOT switch). Это также может быть улучшено в будущем обновлении.

Comments

    Ничего не найдено.