billygoat
billygoat

Reputation: 21984

Is there a way to specify qualifier while performing DI in Angular?

We use services to make HTTP calls to a backend service and inject that service in our controller. The service is dependent on region. We decide on which service to use, based on the user's region. Is there a way to tag services with some qualifier and then perhaps use this qualifier to inject the appropriate service into our controller?

Upvotes: 0

Views: 367

Answers (1)

bluenavajo
bluenavajo

Reputation: 483

In AngularJS there is the concept of providers, which allow you to configure a component a certain way prior to injecting it into other services, controllers etc. The configuration happens at the config phase of an application.

A provider in AngularJS is the most generic approach to components that can be injected into other components. Other facilities like factories and services are just syntactic sugar on top of providers.

Note that if the qualifier changes at runtime, a provider is not the right option. You want to use a factory or service (singleton) that might have a getInstance(qualifier) function returning the right component. The drawback of this would be that you need to have the qualifier available and instantiation would be handled in a manual fashion.

I have created a little example showing how a 'Region' component could be configured based on the region a user is coming from:

var app = angular.module('MyApp', []);

// Specific region component that will be created using a certain preset.
app.factory('SpecificRegion', [
  function() {
    return function(region) {
      var specificRegion = region;
      this.getName = function() {
        return specificRegion;
      }
    }
  }
]);

// The object returned from the $get factory function is available to other
// components as 'Region'.
app.provider('Region', function RegionProvider() {
  var userRegion = 'NO_REGION';

  // Configuration interface for the provider
  this.setRegion = function(region) {
    userRegion = region
  }

  // Actual factory function which configures a component based
  // on a qualifier.
  // It would also be possible to return different components, not only
  // one configured a certain way. Dependency injection for factories
  // is available at this point.
  this.$get = ['SpecificRegion',
    function regionFactory(SpecificRegion) {
      return new SpecificRegion(userRegion);
    }
  ];
});

// Application config phase:
// Configure the region component to behave based on a qualifier.
// The qualifier could come from anywhere, e.g $window.userRegion
app.config(['RegionProvider',
  function(RegionProvider) {
    RegionProvider.setRegion('EMEA');
  }
]);

// Bringing it all together ...
app.controller('MainCtrl', ['$scope', 'Region',
  function($scope, Region) {
    $scope.regionName = Region.getName();
  }
]);
.region {
  color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="MyApp">

  <div ng-controller="MainCtrl">
    <b>Hello from:</b>  <span class="region">{{ regionName }}<span>
  </div>
  
</div>
Editable version on plunker: Region Component

Upvotes: 1

Related Questions