最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Angular.js and ng-switch-when - emulating enum - Stack Overflow

programmeradmin1浏览0评论

I wanted to introduce some enum to my controller logic for some type safety, so for example I created something like this:

var app = angular.module('myApp', []);
var StateEnum = Object.freeze({"login":1, "logout":2})
function LoginCheckCtrl($scope) {
    $scope.stateEnum = StateEnum
    $scope.loginData = StateEnum.login
    $scope.login = function() {
        console.log($scope.loginData  ? 'logged in' : 'not logged in');
        $scope.loginData = StateEnum.logout;
    };
    $scope.logout = function() {
        console.log($scope.loginData ? 'logged in' : 'not logged in');
        $scope.loginData = StateEnum.login;
    };
}

and in my example page I would have something like this:

<div ng-controller="LoginCheckCtrl">
   <div ng-switch on="loginData"> 
      <div ng-switch-when="stateEnum.login" ng-include="'login'"></div>
      <div ng-switch-when="stateEnum.logout" ng-include="'logout'"></div>
   </div>
</div>

<script type="text/ng-template" id="login">
    <button ng-click="login()">Login</button>
</script>

<script type="text/ng-template" id="logout">
    <button ng-click="logout()">Logout</button>
</script>

but ng-switch-when does not want to work. It only works if I substitute values in ng-swith-when manually with integers, for example 1,2.

Here are fiddles to demonstrate this:

/

/

now, as you can see, the first one clearly does not work, and second one works - meaning it changes button when button is clicked.

The problem I think is this var StateEnum = Object.freeze({"login":1, "logout":2}).

Is is possible to use my enum in my html so ng-switch-when will work properly (as in second fiddle)?

I wanted to introduce some enum to my controller logic for some type safety, so for example I created something like this:

var app = angular.module('myApp', []);
var StateEnum = Object.freeze({"login":1, "logout":2})
function LoginCheckCtrl($scope) {
    $scope.stateEnum = StateEnum
    $scope.loginData = StateEnum.login
    $scope.login = function() {
        console.log($scope.loginData  ? 'logged in' : 'not logged in');
        $scope.loginData = StateEnum.logout;
    };
    $scope.logout = function() {
        console.log($scope.loginData ? 'logged in' : 'not logged in');
        $scope.loginData = StateEnum.login;
    };
}

and in my example page I would have something like this:

<div ng-controller="LoginCheckCtrl">
   <div ng-switch on="loginData"> 
      <div ng-switch-when="stateEnum.login" ng-include="'login'"></div>
      <div ng-switch-when="stateEnum.logout" ng-include="'logout'"></div>
   </div>
</div>

<script type="text/ng-template" id="login">
    <button ng-click="login()">Login</button>
</script>

<script type="text/ng-template" id="logout">
    <button ng-click="logout()">Logout</button>
</script>

but ng-switch-when does not want to work. It only works if I substitute values in ng-swith-when manually with integers, for example 1,2.

Here are fiddles to demonstrate this:

http://jsfiddle.net/jNxyE/3/

http://jsfiddle.net/4Jg7M/2/

now, as you can see, the first one clearly does not work, and second one works - meaning it changes button when button is clicked.

The problem I think is this var StateEnum = Object.freeze({"login":1, "logout":2}).

Is is possible to use my enum in my html so ng-switch-when will work properly (as in second fiddle)?

Share Improve this question edited Jun 7, 2016 at 8:03 Efrain 3,3644 gold badges39 silver badges64 bronze badges asked May 18, 2013 at 18:56 AndnaAndna 6,68915 gold badges73 silver badges123 bronze badges
Add a comment  | 

7 Answers 7

Reset to default 13

I think I would create a service that could have all your enums:

angular.module('Enums', []).
   factory('Enum', [ function () {

      var service = {
        freeze: {login:1, logout:2 },
          somethingelse: {abc:1,def:2}
      };

     return service;

    }]);

Your app definition would be like this:

var app = angular.module('myApp', ['Enums']);

Then your controllers you could inject them when you need them:

function LoginCheckCtrl($scope, Enum) {
    if (1==Enum.freeze.login) // as an example
    if (1==Enum.somethingelse.abc)  // another example

Services are singletons so this effectively will give you a set of enums you could define.

As for the ngSwitch when directive, I believe it requires a string (please correct me if I'm wrong). A couple references:

https://groups.google.com/forum/?fromgroups#!topic/angular/EH4W0y93ZAA https://github.com/angular/angular.js/blob/master/src/ng/directive/ngSwitch.js#L171

An alternate way to achieve what you want would be to use ng-show/ng-hide

<div ng-include="'login'" ng-show='stateEnum.login==loginData' ...>

Here's a real world example of how to emulate enums using Angular with standard JavaScript and BootStrap. This is to display details of an order also called a ticket.

Define your enums as Angular constants:

 app = angular.module("MyApp", [])
.constant('ENUMS',
    {
        TicketStatusText: { 0: 'Open', 3: 'Ready', 1: 'Closed', 2: 'Overring' },
        TicketStatus: {Open:0, Ready:3, Closed:1, Overring:2}
    }
    )

Your controller code should look something like this:

app.controller("TicketsController", function ($scope, $http, ENUMS) {
$scope.enums = ENUMS;

Your HTML with BootStrap should look something like this:

<table>
<tr ng-repeat="ticket in tickets" ng-class="{danger:ticket.CurrentStatus==enums.TicketStatus.Overring}">
<td>
<strong>{{ticket.TransNumber}}</strong>
</td>
<td>
{{enums.TicketStatusText[ticket.CurrentStatus]}}
</td>

Notice in ng-class in combination with BootStrap we compare the current status of the ticket model to enums.TicketStatusText.Overring; this will change the color of the row for any tickets that have an Overring status(2).

Also in one of the columns we want to display the ticket status as a string and not as an integer. So this is used: {{enums.TicketStatusText[ticket.CurrentStatus]}}

Have you looked at this answer on stackoverflow?: Ways to enum

Best answer is from 2008, so look at the newer/latest posts for clues. As I read them, you can get the answer as any primitive you need but I haven't tested this yet. Can anyone suggest a best answer to use with Angular from this post?

I would suggest using angular.Module.constant. For instance:

var app = angular.module('app', []);
app.constant('Weekdays', {
    Monday: 1,
    Tuesday: 2,
    Wednesday: 3,
    Thursday: 4,
    Friday: 5,
    Saturday: 6,
    Sunday: 7
});
app.controller('TestController', function(Weekdays) {
    this.weekday = Weekdays.Monday;
});

I have declared some enums in a seperate file called Enums. (I made this withTypeScript) In the controller of the angular app I have something like this:

var app = angular.module("Sample", ["ngAnimate"])
app.controller("Messages", function ($scope, $sce, $interval, $log, $http) {
    $scope.enums = Enums;
};

The enums in the other file are in a var called Enums.

Now you can use this, and even be more creative:

ng-show="anotherVAr == enums.enumOne.VALUE"

Service

var app = angular.module('myApp', []);

app.factory('Enum', function () {
          return {
            Action: {login:1, logout:2 },
            Status: {open:1, close:2}
          };
        });

Controller

app.controller('TestController', function($scope, Enum) {
    $scope.x = Enum.Action.logout;
    $scope.y= Enum.Status.close;
});

ng-switch-when doesn't support expressions and needs a string or number. The typescript transpiler can create reverse mapping between strings and numbers so that stateEnum[1]='login' in your case (or you can create it yourself with a utility function). So you can simply do this, which is a bit ugly but clean.

<div ng-controller="LoginCheckCtrl">
   <div ng-switch on="stateEnum[loginData]"> 
      <div ng-switch-when="login" ng-include="'login'"></div>
      <div ng-switch-when="logout" ng-include="'logout'"></div>
   </div>
</div>
发布评论

评论列表(0)

  1. 暂无评论