要在模板中动态设置控制器,有对与控制器关联的构造函数的引用会有所帮助。控制器的构造函数是传递给controller()
Angular模块 API方法的函数。
这样做会有所帮助,因为如果传递给ngController
指令的字符串不是注册控制器的名称,则将ngController
字符串视为要在当前范围内评估的表达式。此范围表达式需要评估为控制器构造函数。
例如,假设 Angular 在模板中遇到以下情况:
ng-controller="myController"
如果没有myController
注册该名称的控制器,那么 Angular 将查看$scope.myController
当前包含的控制器。如果这个键存在于作用域中并且对应的值是控制器构造函数,那么将使用控制器。
这在ngController
文档中对参数值的描述中提到:“全局可访问构造函数的名称或在当前范围内计算为构造函数的表达式的名称。” Angular 源代码中的代码注释在此处src/ng/controller.js
更详细地说明了这一点。
默认情况下,Angular 无法轻松访问与控制器关联的构造函数。controller()
这是因为当您使用Angular 的模块 API方法注册控制器时,它会将您传递给私有变量的构造函数隐藏起来。您可以在$ControllerProvider 源代码中看到这一点。(controllers
此代码中的变量是私有变量$ControllerProvider
。)
我对这个问题的解决方案是创建一个名为registerController
注册控制器的通用帮助服务。此服务在注册控制器时公开控制器和控制器构造函数。这允许控制器以正常方式和动态方式使用。
registerController
这是我为执行此操作的服务编写的代码:
var appServices = angular.module('app.services', []);
// Define a registerController service that creates a new controller
// in the usual way. In addition, the service registers the
// controller's constructor as a service. This allows the controller
// to be set dynamically within a template.
appServices.config(['$controllerProvider', '$injector', '$provide',
function ($controllerProvider, $injector, $provide) {
$provide.factory('registerController',
function registerControllerFactory() {
// Params:
// constructor: controller constructor function, optionally
// in the annotated array form.
return function registerController(name, constructor) {
// Register the controller constructor as a service.
$provide.factory(name + 'Factory', function () {
return constructor;
});
// Register the controller itself.
$controllerProvider.register(name, constructor);
};
});
}]);
以下是使用服务注册控制器的示例:
appServices.run(['registerController',
function (registerController) {
registerController('testCtrl', ['$scope',
function testCtrl($scope) {
$scope.foo = 'bar';
}]);
}]);
上面的代码在 name 下注册了控制器testCtrl
,它还将控制器的构造函数公开为一个名为 的服务testCtrlFactory
。
现在您可以以通常的方式在模板中使用控制器——
ng-controller="testCtrl"
或动态地——
ng-controller="templateController"
要使后者工作,您必须在当前范围内具有以下内容:
$scope.templateController = testCtrlFactory