molaccha molaccha - 2 years ago 78
Javascript Question

Optional dependencies in AngularJS

I'm trying to implement a controller in AngularJS which is used across multiple pages. It makes use of some services. Some of them are loaded on all pages, some - not. I mean it is defined in different files, and these files are loaded independently. But if I do not load these services on all pages I got error:

Error: Unknown provider: firstOtionalServiceProvider <- firstOtionalService

So, I need to load scripts on all pages. Can I declare dependency as optional in Angular? E.g:

myApp.controller('MyController', ['$scope', 'firstRequiredService', 'secondRequiredService', 'optional:firstOptionalService', 'optional:secondOptionalService', function($scope, firstRequiredService, secondRequiredService, firstOptionalService, secondOptionalSerivce){

// No need to check, as firstRequiredService must not be null

// If the dependency is not resolved i want Angular to set null as argument and check
if (firstOptionalService) {


Answer Source

No, Angular does not yet support optional dependencies out of the box. You'd better put all your dependencies into a module and load it as one Javascript file. If you need another set of dependencies - consider creating another module in another JS and putting all common dependencies to common JS.

However, behavior you've described can be achieved with $injector service. You simply inject $injector instead of all your dependencies to a controller and pull dependencies from it manually, checking if they exist. That's it:


<!DOCTYPE html>
<html data-ng-app="myApp">
    <script src=""></script>
    <script src="app.js"></script>
    <script src="1.js"></script>
    <script src="2.js"></script>
  <body data-ng-controller="DemoController">


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

myApp.service('commonService', function(){
    this.action = function(){
        console.log('Common service is loaded');

myApp.controller('DemoController', ['$scope', '$injector', function($scope, $injector){
    var common;
    var first;
    var second;

        common = $injector.get('commonService');
        console.log('Injector has common service!');
        console.log('Injector does not have common service!');
        first = $injector.get('firstService');
        console.log('Injector has first service!');
        console.log('Injector does not have first service!');
        second = $injector.get('secondService');
        console.log('Injector has second service!');
        console.log('Injector does not have second service!');



myApp.service('firstService', function(){
    this.action = function(){
        console.log('First service is loaded');


myApp.service('secondService', function(){
    this.action = function(){
        console.log('Second service is loaded');

See it live in this plunk! Try to play with <script> tags and watch for console output.

P.S. And, as @Problematic said, you can use $injector.has(), starting from AngularJS 1.1.5.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download