0

Everywhere throughout my website we got links and paths.

http://localhost:3001/controllers/getUsers
http://localhost:3001/controllers/getHouses

http://localhost:8080/assets/img/mypic.png
http://localhost:8080/assets/img/yourpic.png

This is a problem when we switch to production server.

How would you create a "constant" with the path in angular?

const controllerPath = "http://localhost:3001/controllers/"
const imagePath = "http://localhost:8080/assets/img/"

So we can use them in all pages?

I read about these two:

app.constant('controllerPath', 'http://localhost:3001/controllers/');
app.value('controllerPath', 'http://localhost:3001/controllers/');

But then you have to remember to send all paths to all controllers on all pages.

We could put them in $rootScope but then you have to transfer that one to all pages.

Isnt there any "settings" or something similar in Angular where you can setup global constants?

torbenrudgaard
  • 2,375
  • 7
  • 32
  • 53
  • You could use a "main" controller that injects the constant. – Bergur Jun 09 '17 at 23:54
  • Bergur im not sure I understand. Would that be a controller called on each page to set the constants into that pages scope? – torbenrudgaard Jun 09 '17 at 23:56
  • Controller scopes inherit from `$rootScope`, so if you attach it as a property on `$rootScope` they would all be able to access it. – kicken Jun 10 '17 at 00:02
  • @kicken yes but as you see in my question, then I have to send $rootscope to every single controller/page. – torbenrudgaard Jun 10 '17 at 00:08
  • @torbenrudgaard You don't have to inject `$rootScope` specifically. The `$scope` already provided to controllers would work, and your views would have access via it. – kicken Jun 10 '17 at 00:15
  • @kicken nope I tried already. Unless you inject it `app.controller("myController", function ($scope, $rootScope, etc..)` then you will just get `Uncaught ReferenceError: $rootScope is not defined` so you have to do that with every controller on every page, and we got a lot. Thats why it sucks that there are no true "global constants" in angular. – torbenrudgaard Jun 10 '17 at 00:23

2 Answers2

1

You can attach your constants to the $rootScope service which will make them automatically available to any inherited scopes, such as those created for your controllers. Then you can simply access them as properties of your controller's $scope without having to separately inject $rootScope.

angular
 .module('demoApp', ['ngRoute'])
 .controller('page1Controller', ['$scope', function($scope){
  console.log('Asset Prefix: ' + $scope.assetPrefix);
 }])
 .controller('page2Controller', ['$scope', function($scope){
  console.log('Controllers Prefix: ' + $scope.controllersPrefix);
 }]);

angular.module('demoApp').config(['$locationProvider', '$routeProvider', function($locationProvider, $routeProvider){
 $locationProvider.html5Mode(false);
 $routeProvider.when('/page1', {
  controller: 'page1Controller'
  , controllerAs: 'vm'
  , template: '<p>Assets are located at: {{assetPrefix}}</p><a href="#/page2">What about controllers?</a>'
 });
 $routeProvider.when('/page2', {
  controller: 'page2Controller'
  , controllerAs: 'vm'
  , template: '<p>Controllers are located at: {{controllersPrefix}}</p><a href="#/page1">What about assets?</a>'
 });
 $routeProvider.otherwise('/page1');
}]);

angular.module('demoApp').run(['$rootScope', function($rootScope){
 $rootScope.assetPrefix = 'http://localhost:8080/assets';
 $rootScope.controllersPrefix = 'http://localhost:3001/controllers';
}]);

jQuery(function($){
    angular.bootstrap(document, ['demoApp']);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular-route.min.js"></script>
<div>
<div ng-view></div>
</div>
kicken
  • 2,122
  • 14
  • 17
  • Thanks so much for the good example kicken!!. Can I ask what does this one do? `$locationProvider.html5Mode(false)` and what is the advantage of `controllerAs: 'vm'` (other than writing vm.whatever instead of $scope.whatever? – torbenrudgaard Jun 10 '17 at 02:41
  • 1
    [html5Mode(false)](https://docs.angularjs.org/api/ng/provider/$locationProvider) prevents angular from using the [pushState/popState](https://developer.mozilla.org/en-US/docs/Web/API/History) API's and using [controllerAs makes variable access clearer and can remove the need to use `$scope` in many cases](https://stackoverflow.com/questions/32755929/what-is-the-advantage-of-controller-as-in-angular) – kicken Jun 10 '17 at 02:48
0

You have 2 solutions for that:

  • either use $rootScope for all your constant For exemple : $rootScope.controllerPath = ... and inject $rootScope on every controller; that is a common usage.
  • either use the localStorage with that great lib https://github.com/gsklee/ngStorage

You inject $localStorage and use it as $rootScope.

It s a cleaner solution in my point of view

aorfevre
  • 5,034
  • 3
  • 21
  • 51
  • Ahhh $localStorage. didnt know that one - I am gonna check that out right now. Just strange that webpack compiles everything into one big fat js file, but does not make it possible to set constants for that file. – torbenrudgaard Jun 10 '17 at 00:10
  • Okie - got it, would be very useful but you still have to inject it into every controller and page. So you might as well just use $rootScope. Anyway thanks for showing it to me :) – torbenrudgaard Jun 10 '17 at 00:15
  • there is no magical solution. in both solution; you need to inject $rootScope to use global variable. This is not very clean; as $rootScope is your main $scope. ;) the father of all scopes ;) – aorfevre Jun 10 '17 at 00:48