How should I make configurable modules in AngularJS
Asked Answered
S

1

11

I've been tinkering with AngularJS and I've built up a small collection of directives and services that I would like to package into a single JS file so that I can use them anywhere.

I have some website specific settings that my module will need for API calls and that sort of thing. I'm just wondering what the Angular way of making configurable modules is. Obviously I don't want to have to modify my reusable JS file for each website, as that kind of defeats the purpose of having it. Seeing as the values are going to remain the same for each website it seems like an awful lot of hassle to pass them in as an argument on each function call, and I'd rather stay away from global variables as much as possible.

I've searched a lot of questions for the answers I seek, and the closest pattern I've found so far is to have my reusable module be dependant on a not included module called "settings" or something and then define that module in the page's JS file, allowing the reusable module to pull the values from it. Here's an example to show what I mean.

This seems backwards to me. It's kind of like having a function pull values from global values instead of passing the values in as arguments.

Is this really the best way of doing this, or is there an alternative?

Southard answered 12/5, 2014 at 2:9 Comment(0)
D
11

It sounds like you're looking for a provider.

You should use the Provider recipe only when you want to expose an API for application-wide configuration that must be made before the application starts. This is usually interesting only for reusable services whose behavior might need to vary slightly between applications.

Here's a very basic example of a provider:

myMod.provider('greeting', function() {
  var text = 'Hello, ';

  this.setText = function(value) {
    text = value;
  };

  this.$get = function() {
    return function(name) {
      alert(text + name);
    };
  };
});

This creates a new service, just like you might with myMod.service or myMod.factory, but provides an additional API that is available at config time—namely, a setText method. You can get access to the provider in config blocks:

myMod.config(function(greetingProvider) {
  greetingProvider.setText("Howdy there, ");
});

Now, when we inject the greeting service, Angular will call the provider's $get method (injecting any services it asks for in its parameters) and gives you whatever it returns; in this case, $get returns a function that, when called with a name, will alert the name with whatever we've set with setText:

myMod.run(function(greeting) {
  greeting('Ford Prefect');
});

// Alerts: "Howdy there, Ford Prefect"

This is exactly how other providers, like $httpProvider and $routeProvider work.

For more information on providers and dependency injection in general, check out this SO question on dependency injection.

Dead answered 12/5, 2014 at 2:20 Comment(10)
This sounds like exactly what I need. I appear to have completely forgotten how to do DI in Angular over the weekend, so I'll go brush up on that and report back from there.Southard
Hmmm, I'm having trouble getting this to work. I can't seem to get ahold of my provider through DI... plnkr.co/edit/7BXP3bEFDsVQHKmkUjcUSouthard
@YM_Industries Your code is working fine, but your $get is returning settings.password, which is undefined. Did you mean to return settings instead?Dead
Ugh, I guess it's just one of those mornings.Southard
Okay, I think all my reusable stuff is working, but I'm still a little unsure on how to change the settings. I've updated the Plunker to match my progress: plnkr.co/edit/7BXP3bEFDsVQHKmkUjcUSouthard
@YM_Industries I've updated script.js to demonstrate: plnkr.co/edit/L0SKCink67ZqK1hmYjoR?p=previewDead
So just to be clear, AngularJS automatically makes settingsProvider out of settings?Southard
@YM_Industries Yes, because you declared it as a provider. (Technically, every single service, no matter how you create it, gets a provider, but only those created with .provider do anything of significance)Dead
Good to know! Thankyou so much for your help, I think I understand it enough now to carry on on my own.Southard
@YM_Industries No problem! Give me a ping if you run into issues.Dead

© 2022 - 2024 — McMap. All rights reserved.