patternjavascriptMinor
AngularJS constants depending on other constants - any established patterns?
Viewed 0 times
angularjsanypatternsestablisheddependingotherconstants
Problem
I'd like to be able to define Angular constants in terms of other constants.
It's not possible to inject dependencies into Angular
This sets off my code smell for two reasons.
-
I'm using a full-blown call to
-
I'm injecting providers into my
Here's some sample code that shows the above in action. It defines a constant service that's an enumeration type, then it defines another constant service that depends on the enumeration type, and last it calls the
```
app.constant('authLevel', {
Public: "Public",
Admin: "Admin",
SuperAdmin: "SuperAdmin"
});
app.provider("routes", function (authLevel) {
var routes = [
{
path: "/",
controller: "mapsController",
templateUrl: "templates/mapsView.html",
navBarLabel: "LEFT_NAV_BAR.MAPS_NAV_LABEL",
navBarIconClass: "fa-map-marker",
authLevels: [authLevel.Public, authLevel.Admin, authLevel.SuperAdmin],
},
{
path: "/markers",
controller: "markersController",
templateUrl: "templates/markerListView.html",
navBarLabel: "LEFT_NAV_BAR.TABLE_NAV_LABEL",
navBarIconClass: "fa-table",
authLevels: [authLevel.SuperAdmin],
}
];
It's not possible to inject dependencies into Angular
constant services. When I want one of my constants to depend on another of my constants, I use a provider service. This allows my constants to have dependencies (on other constants), but still be used in my .config method call.This sets off my code smell for two reasons.
-
I'm using a full-blown call to
provider when I'm really just defining a constant. It's just that some constants are defined in terms of other constants, and I want to be able to use any of these constants in my .config call.-
I'm injecting providers into my
.config call and then manually calling their $get methods. This seems to just be bypassing some of the tools Angular gives me. It seems to me if I'm calling $get in my own code, it may be a sign that I'm fighting the framework.Here's some sample code that shows the above in action. It defines a constant service that's an enumeration type, then it defines another constant service that depends on the enumeration type, and last it calls the
.config method, injecting the dependent constant service:```
app.constant('authLevel', {
Public: "Public",
Admin: "Admin",
SuperAdmin: "SuperAdmin"
});
app.provider("routes", function (authLevel) {
var routes = [
{
path: "/",
controller: "mapsController",
templateUrl: "templates/mapsView.html",
navBarLabel: "LEFT_NAV_BAR.MAPS_NAV_LABEL",
navBarIconClass: "fa-map-marker",
authLevels: [authLevel.Public, authLevel.Admin, authLevel.SuperAdmin],
},
{
path: "/markers",
controller: "markersController",
templateUrl: "templates/markerListView.html",
navBarLabel: "LEFT_NAV_BAR.TABLE_NAV_LABEL",
navBarIconClass: "fa-table",
authLevels: [authLevel.SuperAdmin],
}
];
Solution
Using an IIFE seems to be the tidiest way I've found to do it. This allows you to define your constant as a function (that is immediately invoked) that returns your constant object so you can use it as normal, i.e: LABELS.appName
References:
.constant('LABELS', (function () {
var self = {};
self.appName = 'MyApp';
self.companyName = 'MyCompany';
self.appHeader = self.appName + ' | ' + self.companyName;
return self;
})());//function is immediately invoked hereReferences:
- SO answer
- Use functions (IIFE) to define AngularJS constants and values
Code Snippets
.constant('LABELS', (function () {
var self = {};
self.appName = 'MyApp';
self.companyName = 'MyCompany';
self.appHeader = self.appName + ' | ' + self.companyName;
return self;
})());//function is immediately invoked hereContext
StackExchange Code Review Q#49558, answer score: 6
Revisions (0)
No revisions yet.