How to compare against global variables in ng-switch
Asked Answered
L

2

6

I am using the AngularJS $rootScope object to expose some global constants that need to be accessible to both controllers and views:

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

app.run(function ($rootScope) {
    $rootScope.myConstant = 2;
});

When I attempt to render a global value in a view, it works correctly:

{{myConstant}}

Equally, if I reference the global value in an ng-if condition it also works:

<span ng-if="someValue == myConstant">Conditional content</span>.

But, when attempting to use the same value for comparison within an ng-switch block, it never evaluates to true. This JSFiddle demonstrates my attempt to get this working. I have also tried explicitly referencing the constant value as a member of $rootScope and as an expression (inside double curly braces) but nothing works.

Any ideas what I'm doing wrong?

Thanks,

Tim

Ladin answered 3/9, 2013 at 14:20 Comment(2)
Doesn't look like it works like that with the ng-switch directive. Others have made similar comments. Here's another jsfiddle that I found that highlights the issue: jsfiddle.net/sfqGBLeonilaleonine
It seems as of now you cannot have a dynamic ng-switch-when. Alternatively, you can use ngIf.Webfooted
B
1

You could always roll your own... :)

(Not sure how efficient this is and it's not well-tested as I just now wrote it)

http://jsfiddle.net/H45zJ/1/

app.directive('wljSwitch', function () {
    return {
        controller: function ($scope) {
            var _value;
            this.getValue = function () {
                return _value;
            };
            this.setValue = function (value) {
                _value = value;
            };

            var _whensCount = 0;
            this.addWhen = function (value) {
                _whensCount++;
            }
            this.removeWhen = function (value) {
                _whensCount--;
            }
            this.hasWhens = function () {
                return _whensCount < -1;
            };
        },
        link: function (scope, element, attrs, controller) {
            scope.$watch(function () {
                return scope.$eval(attrs.wljSwitchOn);
            }, function (value) {
                controller.setValue(value);
            });
        }
    };   
});

app.directive('wljSwitchWhen', function () {
    return {
        require: '^wljSwitch',
        template: '<span ng-transclude></span>',
        transclude: true,
        replace: true,
        link: function (scope, element, attrs, controller) {
            scope.$watch(function () {
                return controller.getValue() === scope.$eval(attrs.wljSwitchWhen);
            }, function (value) {
                if (value) {
                    controller.addWhen();           
                } else { 
                    controller.removeWhen();      
                }
                element.attr('style', value ? '' : 'display:none;');
            });
        }
    };   
});

app.directive('wljSwitchDefault', function () {
    return {
        require: '^wljSwitch',
        template: '<span ng-transclude></span>',
        transclude: true,
        replace: true,
        link: function (scope, element, attrs, controller) {
            scope.$watch(controller.hasWhens, function (value) {
                element.attr('style', value ? '' : 'display:none;');
            });
        }
    };   
});
Brocade answered 3/9, 2013 at 15:57 Comment(0)
K
5

Instead of trying to set ng-switch-when, you can customize ng-switch-on expression in order to produce specific value when myConstant equals item.value:

<span ng-switch on="{true:'const', false: item.value}[myConstant == item.value]">
    <span ng-switch-when="const">
        <span class="blue">{{item.name}}</span> (emphasis applied by ng-switch) 
    </span>
    <span ng-switch-when="4">
        <span class="red">{{item.name}}</span> (emphasis applied by ng-switch) 
    </span>
    <span ng-switch-default>
        {{item.name}}
    </span>
</span>

Working example.

Keynes answered 3/9, 2013 at 14:37 Comment(3)
This is an interesting approach, and it certainly makes my original example work, but isn't this just a different way of creating an "if" condition? My real goal is to use ng-switch to switch between a number of different constant values. Is it possible to adjust your syntax to support that?Ladin
I'd probably run switch on function which will do the same job as expression then. Check out the modified example jsfiddle.net/MmCUr/11 with multiple constants.Thorium
I wonder why this does not work, at least with the latest stable angular release 1.2.2. By looking at the angular sourcecode, i see the following: ng-if watches the scope injected in its link function. ng-switch watches the scope injected in its link function. So under the circumstance, that the $rootScope is available to all other derived scopes, both should resolve their expression variables in the same context.Reduplicative
B
1

You could always roll your own... :)

(Not sure how efficient this is and it's not well-tested as I just now wrote it)

http://jsfiddle.net/H45zJ/1/

app.directive('wljSwitch', function () {
    return {
        controller: function ($scope) {
            var _value;
            this.getValue = function () {
                return _value;
            };
            this.setValue = function (value) {
                _value = value;
            };

            var _whensCount = 0;
            this.addWhen = function (value) {
                _whensCount++;
            }
            this.removeWhen = function (value) {
                _whensCount--;
            }
            this.hasWhens = function () {
                return _whensCount < -1;
            };
        },
        link: function (scope, element, attrs, controller) {
            scope.$watch(function () {
                return scope.$eval(attrs.wljSwitchOn);
            }, function (value) {
                controller.setValue(value);
            });
        }
    };   
});

app.directive('wljSwitchWhen', function () {
    return {
        require: '^wljSwitch',
        template: '<span ng-transclude></span>',
        transclude: true,
        replace: true,
        link: function (scope, element, attrs, controller) {
            scope.$watch(function () {
                return controller.getValue() === scope.$eval(attrs.wljSwitchWhen);
            }, function (value) {
                if (value) {
                    controller.addWhen();           
                } else { 
                    controller.removeWhen();      
                }
                element.attr('style', value ? '' : 'display:none;');
            });
        }
    };   
});

app.directive('wljSwitchDefault', function () {
    return {
        require: '^wljSwitch',
        template: '<span ng-transclude></span>',
        transclude: true,
        replace: true,
        link: function (scope, element, attrs, controller) {
            scope.$watch(controller.hasWhens, function (value) {
                element.attr('style', value ? '' : 'display:none;');
            });
        }
    };   
});
Brocade answered 3/9, 2013 at 15:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.