Подтвердить что ты не робот

Правильный способ использования Typescript перечисления в angular HTML-страницах (например, angular ng-class)

Новое для angular и typescript.

У меня есть typescript enum следующим образом

public enum MyEnum{
   A = 0,
   B = 1,
   C = 2
}

Переменная scope as -

$scope.myLetter: MyEnum = MyEnum.B;

Каков правильный способ проверки перечисления?

Вариант 1: Сравните целочисленное значение перечисления на странице html -

<div ng-class="{classA: myLetter === 0, classB: myLetter === 1, classC: myLetter === 2}">Test panel</div>

Вариант 2: Получить имя класса из метода области управления

$scope.getClass(value: myLetter): string{
    if(value === MyEnum.A)
    return 'classA';

    if(value === MyEnum.B)
    return 'classB';

    if(value === MyEnum.C)
    return 'classC';
}

И иметь элемент html as -

<div ng-class='getClass(myLetter)'>Test panel</div>

Вариант 3: ответ, заданный 'RyanNerd', в Angular.js и ng-switch-when - emulating enum

Для меня предпочтительнее вариант 2, остальные опции имеют проверки в значении ng-class как строку, которая не даст нам статического типа принудительного применения. Поделитесь своими взглядами или любым другим лучшим вариантом, если у вас есть.

4b9b3361

Ответ 1

Получить имя класса из метода области управления

Мне не нравится идея заставить контроллер знать имена классов.

  • Вы можете добавить функцию конвертера в область действия:

    $scope.myEnumName = (value: MyEnum) => MyEnum[value];
    

    и использовать его в шаблоне:

    ng-class="{'A':'ClassA', 'B':'ClassB', 'C':'ClassC'}[myEnumName(myLetter)]"
    
  • Или добавить функцию переключателя

    $scope.switchMyEnum =
        <T>(value: MyEnum, cases: { [value: string]: T }) => cases[MyEnum[value]];
    

    шаблон:

    ng-class="switchMyEnum(myLetter, {'A':'ClassA', 'B':'ClassB', 'C':'ClassC'})
    
  • Если вам нужен только myLetter переключатель:

    $scope.switchMyLetter =
        <T>(cases: { [value: string]: T }) => cases[MyEnum[$scope.myLetter]];
    

    шаблон:

    ng-class="switchMyLetter({'A':'ClassA', 'B':'ClassB', 'C':'ClassC'})
    
  • Если вы хотите использовать несколько перечислений во многих областях:

    angular.module("MyApp", [])
      .run(["$rootScope", (root: {}) => {
        function registerSwitchers(...enumInfos: [string, { [value: number]: string }][]) {
          enumInfos.forEach(enumInfo => {
            var switcherName = enumInfo[0]
            var enumType = enumInfo[1]
            root[switcherName] = (value: any, cases: { [value: string]: any }) => cases[enumType[value]];
          });
        }
        registerSwitchers(
          ["switchMyEnum1", MyEnum1],
          ["switchMyEnum2", MyEnum2]);
      }])
    

Ответ 2

Вы также можете создать объект класса в своем контроллере и установить его как выражение (с записью в виде скобок) в вашем представлении.

Пример: -

$scope.panelClass = {};
$scope.panelClass[MyEnum.A] = 'classA';
$scope.panelClass[MyEnum.B] = 'classB';
$scope.panelClass[MyEnum.C] = 'classC';

Вы можете написать выше, как сокращенный синтаксис (ES6), если ваша версия typescript поддерживает (поддерживает polyfill), поэтому вы можете переписать как:

$scope.panelClass = {
    [MyEnum.A]:'classA',
    [MyEnum.B]:'classB', 
    [MyEnum.C]:'classC'
};

и используйте его как:

<div ng-class="panelClass[myLetter]">Test panel</div>

Это похоже на выражение сокращенного ng-класса:

<div ng-class="{0:'classA', 1:'classB', 2:'classC'}[myLetter]">Test panel</div>

Ответ 3

Обычно нам нужно Enums, когда нам нужно явно указать числовые значения. В приведенном выше примере использования я не вижу явного варианта использования enum s. Массив просто отлично работает, как показано:

((): void => {

 var ClassConstant: string[] = ['classA', 'classB', 'classC'];
 
 angular
  .module('app', [])
  .constant('ClassConstant', ClassConstant)
  .controller('AppController', ($scope, ClassConstant) => {
	  $scope.setClass = (classname: string) => {
		return ClassConstant[classname];
	  };
  });
 })();
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body ng-app="app">

  <div ng-controller="AppController">
    <div ng-class="{{setClass(myLetter)}}">1</div>
  </div>
  
</body>
</html>

Ответ 4

Я тоже столкнулся с этим вопросом.

Это мое решение:

Я создаю функцию в контроллере, которая возвращает логическое значение для каждого значения моего перечисления.

В моем контроллере .ts

export class AController { 
    public TestEnumA(): boolean { 
        return this.scope.field == MyEnum.A; 
    }

    public TestEnumB(): boolean { 
        return this.scope.field == MyEnum.B; 
    }
}

В моем view.html

<div ngController="AController as controllerAlias">
    <div class="a-class" ng-class="{'classA-true': controllerAlias.TestEnumA(), 'classB-true': controllerAlias.TestEnumB()}"><div>
</div>

Почему я выбрал это решение?

Таким образом, я не жестко кодирую класс css в контроллере (жестко закодированный класс css в вашем контроллере, это не является хорошей идеей для обеспечения устойчивости отображения)

Таким образом, я не жестко кодирую значение enum в вашем ng-классе;

Таким образом, я по-прежнему выигрываю от автоматического завершения кода И проверки при компиляции.

Ответ 5

Вы можете указать свой enum в rootScope

angular
    .module('moduleName', [])
    .run(['$rootScope', function ($rootScope) {
        $rootScope.Enum = PathToEnum.Enum;
     }]);
  • pro: его легко настроить, и вы можете использовать его везде (в разных контроллерах или в поле зрения).
  • cons: вы теряете автозаполнение и проверку в компиляции

В представлении

<div ngController="AController">
    <div class="class" ng-class="{$root.Enum.A: 'classA', $root.Enum.B: 'classB'}[valueInScope]">
    </div>
</div>