3

I am trying to remove a great number of string literal values from angular directives all over my views. I have the beginnings of a constant I wish to make global, e.g:

// UI Validation constants. MyAngularApp.constant('valid', { "postalCode": { "pattern": "/^[0-9]+$/", "minLength": 4 } }); 

Then I would like to use this constant in input directives in my view templates, in a way similar to:

<input type="text" ng-pattern="{{valid.postalCode.pattern}}" blah blah> 

But here I have serious doubts about binding within a directive's parameter.

I have seen a few suggestions to add such a constant to root scope, but also some suggestions to avoid root scope and only add this to local scopes inside controllers, but this would involve code changes to several controllers, where I would prefer just one change.

if I decide to go with root scope, how would I add this constant? My misguided attempt at this is:

console.log("Abandon all hope who enter here!"); MyAngularApp.config(function ($rootScope) { $rootScope.valid = valid; // How to access the constant here? }); 

But this code gives me the error:

Uncaught Error: [$injector:modulerr]

ADDED: Some suggestions below involve the Angular run function, but I can't find that. The module call is like this:

var MyAngularApp = angular.module('MlamAngularApp', ['kendo.directives', 'ngRoute', 'ui.bootstrap', 'ngReallyClickModule', 'ngMessages', 'angular-loading-bar', 'ngAnimate']); 
2
  • You need to inject constant, MlamAngularApp.config(function ($rootScope, valid){ Commented May 11, 2015 at 6:23
  • check my updated answer for how to use the run block Commented May 11, 2015 at 7:06

2 Answers 2

3

Per the OP - If you want to bind to rootScope you when the app loads you can use a run block like this:

app.run(function($rootScope) { $rootScope.name = 'bound during run' }) 

I updated the plunker demonstrating scope inheritance to show it in action.

Plunker

It's bad practice to store stuff in $rootScope. Here is an example why:

$scope inheritance

It can make things confusing and messy, especially if multiple people are maintaining code. You bind something to rootScope and EVERY controller's scope has that property attached to it's scope. If you have to do it, you should document it very clearly.

Do it like this:

app.constant('myConstant', { "postalCode": { "pattern": "/^[0-9]+$/", "minLength": 4 } }) 

Just inject wherever you need it:

app.controller('MainCtrl', function($scope, myConstant) { $scope.name = myConstant; }); 

Banner's method is fine as well, though I think it is better to do it this way to maintain a high level of abstraction rather than attaching a bunch of stuff to the module like that. This way let's you tuck all your constants into constants.js or whatever, and keeps everything clean.

Sign up to request clarification or add additional context in comments.

13 Comments

If these are constants, these are globals. I disagree It's bad practice to store stuff in $rootScope.
Yes, @CyrilCHAPON, these are values that are only ever changed at 'compile time', by a developer, and never change in the course of the app, so I also disagree that global is wrong here.
If they are constants it doesn't seem like they should be defined in rootScope. rootScope isn't constant. You are free to disagree as well. :) If you care to elaborate on why it's not, then by all means. There are two sides to the issue. I agree that rootScope is there for a reason, so if you have a good reason to use it, use it. But in this case I don't think it's a good reason.
Ok for constants != rootScope. Good point, but to clarify I'm not saying that this precise use case is not a "good reason", I'm saying It's bad practice to store stuff in $rootScope. is a lil opiniated and kinda hard
Ok buddy. Got it. Thanks for clarification and edit. Though, as a personal opinion, I find that You bind something to rootScope and EVERY controller's scope has that property attached to it's scope, in that precise case, would facilitate and clarify his codebase. I wouldn't want to inject a service (even a wrapper one) in each controller where I want to use a string. Plus some parts of the HtML page are certainly not handled by a controller at all, but he might want to use strings here too.
|
0

See the snippet. valid constant is getting injected into $rootScope when calling run.

On the view side, just do {{$root.valid.postalCode.pattern}} where you need to inject it.

And thus... the only thing that you need to change is the run function and the corresponding views' binding.

Injecting into config will not work as per Cannot get to $rootScope

(function() { 'use strict'; angular.module('myApp', []); angular.module('myApp') .constant('valid', { "postalCode": { "pattern": "/^[0-9]+$/", "minLength": 4 } }); angular.module('myApp') .run(runFn); runFn.$inject = ['$rootScope', 'valid']; function runFn($rootScope, valid) { $rootScope.valid = valid; } angular.module('myApp') .controller('myCtrl', myCtrl); function myCtrl() { var self = this; } }());
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <div ng-app="myApp" ng-controller="myCtrl as vm"> {{$root.valid.postalCode.pattern}} </div>

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.