Правильный способ использования 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 как строку, которая не даст нам статического типа принудительного применения. Поделитесь своими взглядами или любым другим лучшим вариантом, если у вас есть.
Ответы
Ответ 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>