11

I have written a module in angularJS that encapsulates all the backend communications. For greater flexibility I have the api prefix as a constant value on the module (could be value since I am not using it in the config phase). so something like

angular.module('myapp.data').constant('apiPrefix', '/api/data');

Now I want to use this module from two different applications. One uses /api1/data and the other one /api2/data and I would like to change this during the config phase of the application. I know how to do that with a provider, but having a provider to hold a value seems like an overkill to me. Can I modify used modules constants or values from the application config phase?

something like:

angular.module("data", [])
.value('apiPrefix', '/api/data')
.factory('display', function(apiPrefix){
  return {
    pref: function(){
      console.log(apiPrefix);
      return apiPrefix;
    }
  }
});


angular.module("myApp",['data'])
.config(['apiPrefix', function(prefix){
  prefix = 'https:/api/data'; 
}])
.controller("Example", function($scope, display) {
   $scope.prefix = display.pref;
});
masimplo
  • 3,674
  • 2
  • 30
  • 47
  • 1
    Not sure but you can try to do it at `run` stage. – Chandermani Apr 09 '14 at 16:03
  • Yeah you can update a value at the run stage, and you can inject a constant in config but since it's a constant it can't be changed http://stackoverflow.com/questions/13035568/angular-js-value-not-injected-in-config – shaunhusain Apr 09 '14 at 16:06
  • So what you are saying is that it should be a value instead of a constant in the module and modify it on run stage of the application instead of the config? – masimplo Apr 09 '14 at 16:09
  • Why don't you give it a try :) – Chandermani Apr 09 '14 at 16:10
  • Indeed that is what we're saying. Config needs to be run on everything that could have config before it is injected into anything hence the problem. – shaunhusain Apr 09 '14 at 16:10

3 Answers3

12

to override the module values, you can redefine the angular value in later modules. I believe it should not be done module config time.

angular.module("data", [])
.value('apiPrefix', '/api/data')
.factory('Display', function(apiPrefix){
  return {
    pref: function(){
      return apiPrefix;
    }
  }
});




angular.module('myapp', ['data'])
  .value('apiPrefix', '/api2/data')
  .controller('MainCtrl', function($scope, Display)    {
      $scope.name = Display.pref();
  });

see the plunker here: http://plnkr.co/edit/k806WE

same thing is applicable for angular constants too.

khanmizan
  • 926
  • 9
  • 17
  • 2
    Great solution. I kind of fill bad that I didn't know that since I could have accidentally override a module constant or value, since I am using them a lot. Good thing I am always trying to create unique descriptive names. – masimplo Apr 10 '14 at 08:20
  • Thanks @mxa055. Actually, I prefer to keep constants and values like configuration or backend api endpoints in a seperate config module. – khanmizan Apr 10 '14 at 08:35
11

Our module

angular.module("data", [])
  .constant('apiPrefix', '/api/data');

We can override constant fully, like value.

angular.module('myapp', ['data'])
  .constant('apiPrefix', '/api2/data');

also we can override fully in config

angular.module('myapp', ['data'])
    .config(function ($provide) {
        $provide.constant('apiPrefix', '/api2/data');
    });

also we can override fully or partially (if object) in run

angular.module('myapp', ['data'])
    .run(function (apiPrefix) {
        apiPrefix = '/api2/data';
    });

But if we want to override constant with object partially in config (not in run), we can do something like this

angular.module("module1", [])
    .constant('myConfig', {
        param1: 'value1' ,
        param2: 'value2'
    });

angular.module('myapp', ['data'])
    .config(function ($provide, myConfig) {
        $provide.constant(
            'myConfig', 
            angular.extend(myConfig, {param2: 'value2_1'});
        );
    });
  • 1
    Reference myConfig with string to override extend values on module myapp. angular.module('myapp', ['data']) .config(function ($provide, myConfig) { $provide.constant( myConfig, angular.extend('myConfig', {param2: 'value2_1'}); ); }); – chicoxin Feb 09 '18 at 17:39
  • 1
    Thanks. Yes, `$provide.constant('myConfig', ...` - 'myConfig' must be a string! – Alexander Anikeev Feb 12 '18 at 13:04
1

Angular modules, controllers, etc. can be contained within functions, if-statements, etc. They do not have to be at the top level. So, you could include this in your code:

if (environmentOne()) {
  module.value('apiPrefix','api1/data');
} else {
  module.value('apiPrefix','api2/data');
}

Hope that helps!

Robert Balicki
  • 1,583
  • 2
  • 16
  • 24
  • This sounds interesting, but I would hate to have to do something like that in my module for every different application that might use me. It short of creates a "dependency" between the module and its users. – masimplo Apr 09 '14 at 17:13
  • Ah, you're right. I misread your question, and thought it was a matter of development/staging/production environments. Khanmizan's answer is better. – Robert Balicki Apr 09 '14 at 17:19