5

I got services in angular that I need to be configurable, this way I can remove coupling from my app and share some of my code.

My question is how do you achieve this ?

With module.value() and dependancy injection ? Then how do you get a default value ? How do you make a value calculated at init and not hardcoded ?

With a another service ? How do you make that generic ?

Do you have a code exemple, because I'm a bit lost with this.

Bite code
  • 578,959
  • 113
  • 301
  • 329
  • What do you mean by calculated at init and not hard-coded? You can update values created with module.value just not module.constant, you can also use ng-init, you could potentially fetch some data asynchronously then setup injected module.value() – shaunhusain Jul 17 '13 at 06:48
  • Let's say I want to get the config value, make an asynchronous call with it, get a value back and then inject that in my service. – Bite code Jul 17 '13 at 07:21
  • Yah so if I understand correctly, you read some config value that was previously set with a module.value(key,value) call, grabbing the value by calling $injector.get(key), if you're not sure that the injector has been configured with that key you can surround with a try catch block and can give it some default in either case you can use module.value() again I believe to add or change any of the values to inject. Perhaps you're concerned with angular having injected the values for services etc. in advance of your updating them, I believe $injector.get() will retrieve the latest value for you. – shaunhusain Jul 17 '13 at 07:26
  • Ah okay I reread your question a few more times here, so you're looking for something more like a properties file you would get in Java where you configure a list of things that lives outside of the service but is used to configure it? If so you could just use a separate JS file where you set all the module.value calls and you can use something like GruntJS to setup a build configuration that loads the appropriate JS file depending on your build target (or perhaps even have it re-write some files though I'm not sure what grunt tasks are available for this) – shaunhusain Jul 17 '13 at 07:46
  • This can't be that complicated. I don't want to beleive that. No. Nooooooooooooo. – Bite code Jul 17 '13 at 07:51
  • possible duplicate of [How should I make configurable modules in AngularJS](http://stackoverflow.com/questions/23600051/how-should-i-make-configurable-modules-in-angularjs) – Bite code Aug 20 '14 at 06:05
  • 1
    I vote to close my own question because I found the answer on SO here : http://stackoverflow.com/questions/23600051/how-should-i-make-configurable-modules-in-angularjs – Bite code Aug 20 '14 at 06:06
  • I would have actually known this answer had I seen the question a year later :P, glad you found the custom provider definition solution though since that opens up the ability to configure a service. For me personally writing directives has helped keep things DRY and modular... services I typically still write per app though there may be some benefit to further abstracting on top of $resource the complexity hasn't seemed worth the trade off to me. – shaunhusain Aug 20 '14 at 19:23

2 Answers2

7

In order to create a configurable service, you need to use a provider, see: http://docs.angularjs.org/guide/providers. Providers allow you to configure the factory or service in the module's config block before it is instantiated. For a simple example, see http://plnkr.co/edit/QMLBBQ3obE90FtCA2eBu

For a more complete/complex example of how to use configurable services, I would suggest looking at the Restangular project, which also demonstrates a method of providing default values that can be overriden by the app developer.

dspies
  • 1,545
  • 14
  • 19
1

I believe something like this should work within your service, if you were to use .value() to declare some objects for injection

var myLocalValue = myInjectedValue || "Some default value";

I'm not super javascript savvy but this answer on SO seems to elude to the fact that this will work too: JavaScript OR (||) variable assignment explanation

I made a fiddle here to test it out it seems to work how I would expect:

http://jsfiddle.net/u3MY8/1/

JavaScript

var app = angular.module("myapp",[]);
// define a value
app.value('myThing', 'weee');

// use it in a service
app.factory('myService', ['myThing', function(myThing, myOtherThing){
    var myLocalOtherThing = myOtherThing || "some default";
   return {
       whatsMyThing: function() { 
          return myThing; //weee
       },
       whatsMyOtherThing: function() {
           return myOtherThing;
       },
       whatsMyOtherThingWithDefault: function() {
           return myLocalOtherThing;
       }
    }
}]);

// use it in a controller
app.controller('someController', function($scope, myService) {
    $scope.foo = myService.whatsMyThing(); //weee
    $scope.bar = myService.whatsMyOtherThing(); //""
    $scope.baz = myService.whatsMyOtherThingWithDefault(); //some default
});

HTML

<div ng-app="myapp" ng-controller="someController">
    <ol>
        <li>{{foo}}</li>
        <li>{{bar}}</li>
        <li>{{baz}}</li>
    </ol>
</div>

To note this only works if myOtherThing isn't injected, if you list it to be injected but it hasn't been defined you'll run into errors, but I'm not sure exactly what the use case is.

Community
  • 1
  • 1
shaunhusain
  • 19,630
  • 4
  • 38
  • 51
  • How do you pass myOtherThing without injecting it ? You setup the service manually ? It seems to me that it defeat the purpose of using angularjs? – Bite code Jul 17 '13 at 07:08
  • Alright so I updated the fiddle a couple of times since i see what you're saying if you can't inject it without error without knowing that it was declared then you can't make a default... instead I'm using the $injector service to .get() the service, and surrounding it with a try catch block in case it's not declared. http://jsfiddle.net/u3MY8/3/ – shaunhusain Jul 17 '13 at 07:21
  • Ok, I'll +1 because that will work (at least synchronously), but I can't imagine this would be the right way to do it. There must be another way... – Bite code Jul 17 '13 at 07:50
  • @e-satis it's very likely I'm still learning a lot in Angular so there may be a better way I'm just shooting from the hip based on what I know so far. – shaunhusain Jul 17 '13 at 08:09