1

I've been trying to get the value of the nested constants inside the angular constants using angular filter. But I can't find an efficient way to get the values. I'm allowed to use lodash "^2.4.1" and i tried using _.pick but still i could only access the root level constants and not the nested ones.

//consider this
angular.module('myApp',[])

.constants('appConstants', {
    CONS1: 'root',
    CONS2: {
          NEST1: 'nested cons1',
          NEST2: 'nested cons2',
    }
)
.filter(getConstants, function  () {
    return function  (input) {
        var value =  appConstants[input];
        if (! value) {
            var keys = input.split('.');
            value =  appConstants;
            angular.forEach(keys, function(key, index) {
                value = value[key];
            });
        }
        return value;
    }
});

//where as
appConstants[CONS1]; //works
appConstants[CONS2.NEST1]; // return undefined
//in lodash
_.pick(appConstants, 'CONS2.NEST1'); // returns empty object
Balajee Ks
  • 327
  • 7
  • 18

3 Answers3

2

Using AngularJS constants

An AngularJS constant is just the value (here an object) it is defined to be.

{
    CONS1: 'root',
    CONS2: {
          NEST1: 'nested cons1',
          NEST2: 'nested cons2',
    }
}

To get NEST1, use the usual property accessors, the dot notation appConstants.CONS1.NEST1 or the bracket notation appConstants["CONS1"]["NEST1"].


Accessing the constants in the HTML template

The simplest way is just to add the constant object into the $rootScope.

angular.module('myApp', [])
    .constants('appConstants', {
        CONS1: 'root',
        CONS2: {
            NEST1: 'nested cons1',
            NEST2: 'nested cons2',
        }
    })
    .run(function($rootScope, appConstants) {
        $rootScope.CONSTANTS = appConstants;
    });

And in any template, just use CONSTANTS as an object.

<span>{{ CONSTANTS.CONS2.NEST1 }}</span> 

Source: Can I directly access module constant from HTML under AngularJS


Using Lodash

If you really want to use lodash, use the _.get function which enables complex path to resolve to the right nested object.

_.get(appConstants, "CONS1.NEST1");

So a filter could be as simple as:

.filter("const", function() {
    return function(input) {
        return _.get(appConstants, input);
    };
});

Pass a string path to the filter to get a value.

{{ "CONS2.NEST1" | const }}

Built-in alternative to Lodash

Amy Blankenship presents Angular's $parse in her answer which, in my opinion, is a better approach than Lodash in this case.


I can't use _.get because I'm allowed to use the older version of lodash 2.4.1.

There are two options:

_.get is quite complex, but for our simple case, a simple string split on dots would probably do.

.filter("getConstants", function() {
    return function(input) {
        var obj = appConstants,
            path = input.split('.'),
            index = 0,
            length = path.length;

        while (obj != null && index < length) {
            obj = obj[path[index++]];
        }
        return obj;
    };
});
Community
  • 1
  • 1
Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129
  • I can't use _.get because I'm allowed to use the older version of lodash 2.4.1. The problem is I could pass the object path as String from my view (html). {{ CONS2.NEST1 | getConstant}} <- this won't work and gives me undefined when it reaches the filter. So I am passing it to filter as -> {{' CONS2.NEST1' | getConstant}} – Balajee Ks Feb 16 '17 at 16:41
  • 1
    @BalajeeKs I added a section related to lodash 2.4.1. – Emile Bergeron Feb 16 '17 at 16:56
  • @BalajeeKs please do not edit the code inside other's post. The code works as-is and already takes care of root level properties. See [When should I make edits to code?](http://meta.stackoverflow.com/a/260246/1218980) – Emile Bergeron Feb 16 '17 at 18:34
  • @BalajeeKs I added a better approach using the `$rootScope` that you might want to try out. – Emile Bergeron Feb 16 '17 at 20:56
  • I've previously used $rootscope throughout the application but I was advised not to use it. Which is why I've thought of creating a filter. I find AmyBlankenship 's solution to be perfect approach rather than writing my own function. – Balajee Ks Feb 17 '17 at 05:31
  • 1
    @BalajeeKs While I agree that polluting the `$rootScope` is not a good idea, our case here is one of the reason to use it. It's THE most efficient way. Using `$parse` for a filter is better than using Lodash, but not better than [exposing the constants in the `$rootScope` like most seems to agree](http://stackoverflow.com/questions/17505138/can-i-directly-access-module-constant-from-html-under-angularjs). – Emile Bergeron Feb 17 '17 at 14:47
2

You also have the option of using the Angular $parse function. I think this will work if you provide it with your root constant object as the context parameter.

That might look something like:

$parse(input)(appConstants)
Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129
Amy Blankenship
  • 6,485
  • 2
  • 22
  • 45
0

You've forgotten closing brace ( '}' ) in the constant declaration.

Maybe try this :

.constants('appConstants', {
    CONS1: 'root',
    CONS2: {
          NEST1: 'nested cons1',
          NEST2: 'nested cons2',
    }
})
Je.
  • 34
  • 5