Self explanatory fiddle: /
I need to dynamically choose the controller to use at runtime based on its name as a string. The string will be read from a config object.
In the code below I currently have InnerCtrlAsLocalVariable
assigned to $scope.dynamicCtrl
. How instead do I assign InnerCtrlFromModule
to the property?
View:
<div ng-app='app' ng-controller='OuterCtrl'>
<div ng-controller='dynamicCtrl'>
{{message}}
</div>
</div>
JS:
var InnerCtrlAsLocalVariable = ['$scope',
function($scope) {
$scope.message = 'from controller as local variable - do not want'
}
];
angular.module('app', [])
.controller('OuterCtrl', ['$scope',
function($scope) {
// Instead of doing this...
$scope.dynamicCtrl = InnerCtrlAsLocalVariable;
// ...I want to do something like this:
// $scope.dynamicCtrl = resolveCtrl('InnerCtrlFromModule');
}
])
.controller('InnerCtrlFromModule', ['$scope',
function($scope) {
$scope.message = 'from controller defined in module - want';
}
]);
Self explanatory fiddle: http://jsfiddle/5FG2n/6/
I need to dynamically choose the controller to use at runtime based on its name as a string. The string will be read from a config object.
In the code below I currently have InnerCtrlAsLocalVariable
assigned to $scope.dynamicCtrl
. How instead do I assign InnerCtrlFromModule
to the property?
View:
<div ng-app='app' ng-controller='OuterCtrl'>
<div ng-controller='dynamicCtrl'>
{{message}}
</div>
</div>
JS:
var InnerCtrlAsLocalVariable = ['$scope',
function($scope) {
$scope.message = 'from controller as local variable - do not want'
}
];
angular.module('app', [])
.controller('OuterCtrl', ['$scope',
function($scope) {
// Instead of doing this...
$scope.dynamicCtrl = InnerCtrlAsLocalVariable;
// ...I want to do something like this:
// $scope.dynamicCtrl = resolveCtrl('InnerCtrlFromModule');
}
])
.controller('InnerCtrlFromModule', ['$scope',
function($scope) {
$scope.message = 'from controller defined in module - want';
}
]);
Share
edited May 13, 2015 at 13:56
Khanh TO
49k13 gold badges101 silver badges116 bronze badges
asked Jan 18, 2014 at 12:53
Mike ChamberlainMike Chamberlain
42.6k28 gold badges113 silver badges159 bronze badges
6
- Why do need a controller to be assigned to variable? You share data through service. – Fizer Khan Commented Jan 18, 2014 at 13:01
- Even though i really do not understand the purpose, You can choose dynamic template(inner-local-template.html, inner-module-template.html') instead of choosing dynamic controller. – Fizer Khan Commented Jan 18, 2014 at 13:14
- This is not for sharing data, this is so I can dynamically choose the controller at runtime. – Mike Chamberlain Commented Jan 18, 2014 at 13:15
- I am already choosing the template dynamically using by binding the src property on ng-include. But the same template might use different controllers in different circumstances. Therefore, I need to avoid hard coding the controller name into the template. – Mike Chamberlain Commented Jan 18, 2014 at 13:16
- I could not find a way to inject or resolve a controller dynamically. – Fizer Khan Commented Jan 18, 2014 at 13:41
2 Answers
Reset to default 8You could try writing custom directive:
.directive("ngDynamicController",function($pile){
return {
terminal: true,
priority: 1000,
link:function(scope,element,attr){
var controllerProperty = scope[attr.ngDynamicController];
element.attr('ng-controller', controllerProperty);
element.removeAttr("ng-dynamic-controller");
$pile(element)(scope);
}
}
})
If you need more information why we have to add terminal: true
and priority: 1000
. Check out my answer to this question: Add directives from directive in AngularJS
DEMO
You could try injecting it as a value:
angular.module('app', [])
.value('InnerCtrl',InnerCtrlAsLocalVariable)
.controller('OuterCtrl', ['$scope','InnerCtrl',
function($scope, InnerCtrl) { //inject the value into the function
$scope.dynamicCtrl = InnerCtrl;
}
])
DEMO
Or use $injector to resolve dynamically:
var InnerCtrlAsLocalVariable = ['$scope',
function($scope) {
$scope.message = 'from controller defined in module - want';
}
]
angular.module('app', [])
.value('InnerCtrl',InnerCtrlAsLocalVariable)
.controller('OuterCtrl', ['$scope','$injector',
function($scope, $injector) { //inject the $injector service.
// resolve the value dynamically
$scope.dynamicCtrl = $injector.get('InnerCtrl');
}
])
.controller('InnerCtrlFromModule', InnerCtrlAsLocalVariable)
DEMO
You can use $controller
service to create the controller instance dynamically, from that instance we can retrieve the constructor function using constructor
property
angular.module('app', [])
.controller('OuterCtrl', ['$scope','$controller',
function(scope, $controller) {
scope.dynamicCtrl = $controller('InnerCtrlFromModule',{$scope:scope.$new()}).constructor;
}
])
.controller('InnerCtrlFromModule',['$scope', function($scope) {
$scope.message = 'from controller defined in module - want';
}])
DEMO
You don't need to dynamically choose the controller. Use a single controller and use DI to provide different functionality to that controller.
angular.module('app', [])
.service('ControllerService', function() {
this.get = function(controllerName) {
// ... do your logic for returning the controller functionality here
if (controllerName == "fooController") {
return {
foo: function() { return "foo" }
}
}
else {
return {
foo: function() { return "bar" }
}
}
});
})
.controller('SingleController', ['$scope', 'ControllerService',
function($scope, ControllerService) {
$scope.functionality = ControllerService.get('fooController');
});
You bind to the functionality
object on your controller:
<div ng-controller="SingleController">
<p>{{functionality.foo()}}</p>
</div>