How to check if an angularjs controller has been defined

橙三吉。 提交于 2019-12-04 03:09:58

问题


I've got an app defined this way:

angular.module("myApp", [...])
  .config(function ($stateProvider, $controllerProvider) {
    if (isControllerDefined(controllerName)) {
      do_stuff();
    }
  })

The controllers are defined this way:

angular.module("myApp")
  .controller("myController", function ($scope) { ... });

How can I define isControllerDefined() (in the config above) to check whether a given controller exists if I have the name of the controller? I feel like I should be able to do something like one of these:

var ctrl = angular.module("myApp").getController("myController");
var ctrl = $controllerProvider.get("myController");

or something like that... but I can't find any functionality for this. Help?


回答1:


An example of a service that can check if a controller exists. Note that it looks for a global function with specified name as well as a controller in the $controller provider.

angular.service('ControllerChecker', ['$controller', function($controller) {
  return {
    exists: function(controllerName) {
      if(typeof window[controllerName] == 'function') {
        return true;
      }
      try {
        $controller(controllerName);
        return true;
      } catch (error) {
        return !(error instanceof TypeError);
      }
    }
  };
}]);

See the fiddle for usage.




回答2:


I came across this exact same issue the other day. I had a few issues with the currently accepted answer, namely because one of my controllers was performing an initialization call out to the server upon instantiation to populate some data (i.e):

function ExampleController($scope, ExampleService) {
    ExampleService.getData().then(function(data) {
        $scope.foo = data.foo;
        $scope.bar = data.bar
    });
}

As it stands, the currently accepted answer will actually instantiate the controller, before discarding it. This lead to multiple API calls being made on each request (one to verify that the controller exists, one to actually use the controller).

I had a bit of a dig around in the $controller source code and found that there's an undocumented parameter you can pass in called later which will delay instantiation. It will, however, still run all of the checks to ensure that the controller exists, which is perfect!

angular.factory("util", [ "$controller", function($controller) {
    return {
        controllerExists: function(name) {
            try {
                // inject '$scope' as a dummy local variable
                // and flag the $controller with 'later' to delay instantiation
                $controller(name, { "$scope": {} }, true);
                return true;
            }
            catch(ex) {
                return false;
            }
        }
    };
}]);

UPDATE: Probably a lot easier as a decorator:

angular.config(['$provide', function($provide) {
    $provide.delegate('$controller', [ '$delegate', function($delegate) {
        $delegate.exists = function(controllerName) {
            try {
                // inject '$scope' as a dummy local variable
                // and flag the $controller with 'later' to delay instantiation
                $delegate(controllerName, { '$scope': {} }, true);
                return true;
            }
            catch(ex) {
                return false;
            }
        };

        return $delegate;
    }]);
}]);

Then you can simply inject $controller and call exists(...)

function($controller) {
    console.log($controller.exists('TestController') ? 'Exists' : 'Does not exist');
}



回答3:


There is currently no easy way of fetching a list of controllers. That is hidden for internal use only. You would have to go to the source code and add a public method that return the internal controllers variable (in $ControllerProvider function) https://github.com/angular/angular.js/blob/master/src/ng/controller.js#L16

this.getControllers = function() {
    return controllers;
    // This will return an object of all the currently defined controllers
  };

Then you can just do

app.config(function($controllerProvider) {
    var myCtrl = $controllerProvider.getControllers()['myController'];
});



回答4:


Since angular 1.5.1 (not released yet at the time of writing), there is a new way to check whether a controller exists or not through the $ControllerProvider.has('MyCtrlName') method.

Github issue: https://github.com/angular/angular.js/issues/13951

Github PR: https://github.com/angular/angular.js/pull/14109

Commit backported in 1.5.1 directly: https://github.com/angular/angular.js/commit/bb9575dbd3428176216355df7b2933d2a72783cd


Disclaimer: Since many people were interested by this feature, I made a PR, because I also need it is some of my projects. Have fun! :)

This PR has been based on @trekforever answer, thanks for the hint :)




回答5:


You could use the $controller service and do $controller('myController') and wrap a try-catch arround it so you know if it fails.



来源:https://stackoverflow.com/questions/19734565/how-to-check-if-an-angularjs-controller-has-been-defined

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!