web-dev-qa-db-ja.com

angular HTMLページでTypeScript列挙型を使用する正しい方法(例:angular ng-class)

angularおよびTypeScriptの新機能。

次のようにTypeScript列挙型があります

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

スコープ変数as-

$scope.myLetter: MyEnum = MyEnum.B;

列挙チェックを行う正しい方法は何ですか?

オプション1:htmlページのenumの整数値を比較します-

<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要素として

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

オプション3:Angular.jsおよびng-での 'RyanNerd'による回答switch-when-列挙型のエミュレート

私にとってはオプション2が望ましいです。残りのオプションでは、ng-class値を文字列としてチェックします。これにより、静的な型の強制は行われません。もしあれば、あなたの意見や他のより良いオプションを共有してください。

24
Trans

コントローラースコープメソッドからクラス名を取得する

コントローラにクラス名を知ってもらうという考えは好きではありません。

  1. スコープにコンバーター関数を追加できます。

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

    テンプレートで使用します:

    ng-class="{'A':'ClassA', 'B':'ClassB', 'C':'ClassC'}[myEnumName(myLetter)]"
    
  2. またはスイッチ機能を追加

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

    テンプレート:

    ng-class="switchMyEnum(myLetter, {'A':'ClassA', 'B':'ClassB', 'C':'ClassC'})
    
  3. myLetterスイッチのみが必要な場合:

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

    テンプレート:

    ng-class="switchMyLetter({'A':'ClassA', 'B':'ClassB', 'C':'ClassC'})
    
  4. 多くのスコープで多数の列挙を使用する場合:

    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]);
      }])
    
9
Artem

また、コントローラーでクラスオブジェクトを構築し、ビューで式(括弧表記)として設定することもできます。

例:-

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

TypeScriptバージョンがサポートしている(ポリフィルをサポートしている)場合は、上記を簡易構文(ES6)として記述できるため、次のように書き換えることができます。

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

そしてそれを次のように使用します:

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

これは、簡単なng-class式に似ています。

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

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>
1
rdhainaut

通常、数値を明示的に参照する必要がある場合は、Enumsが必要です。上記のユースケースでは、enumsを使用する明示的なユースケースは見当たりません。以下に示すように、配列は正常に機能します。

((): 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>
1
Aditya Singh

私もこの質問に直面しました。

これは私のソリューションです:

列挙型の各値に対してブール値を返す関数をコントローラーで作成します。

私のcontroller.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>

なぜこのソリューションを選択したのですか?

このように、I ハードコードしないでくださいコントローラーのcssクラス(コントローラーのcssクラスをハードコードしました。ビューの保守性を確保することはお勧めできません)

このように、I ハードコードしないでください ng-classの列挙値;

このように、自動コード補完のメリット AND コンパイル時の検証

1
rdhainaut