テンプレートでコントローラーを動的に設定するには、コントローラーに関連付けられたコンストラクター関数への参照があると役立ちます。コントローラーのコンストラクター関数は、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';
}]);
}]);
上記のコードは、コントローラーを という名前testCtrl
で登録し、コントローラーのコンストラクターを というサービスとして公開しtestCtrlFactory
ます。
これで、通常の方法でテンプレートでコントローラを使用できます--
ng-controller="testCtrl"
または動的に--
ng-controller="templateController"
後者が機能するには、現在のスコープに次のものが必要です。
$scope.templateController = testCtrlFactory