Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I resolve and assign an inner controller from the outer's scope?

Self explanatory fiddle: http://jsfiddle.net/5FG2n/1/

Say I have a view with two controllers, one containing the other. The outer controller is static, but I need to set the inner controller based on a scope variable from the outer. The scope variable will be the inner controller's name as a string (eg. 'InnerCtrl').

Here's the view:

<div ng-app='app' ng-controller='OuterCtrl'>
    <div ng-controller='dynamicCtrl'>
        {{result}}
    </div>
</div>

And here's the module that is not yet correct:

angular.module('app', [])

    .controller('OuterCtrl', ['$scope', 
        function($scope) {

            // Instead of hard coding the controller here,
            // how do I resolve the string 'InnerCtrl' to the 
            // controller function defined below, so it can be
            // assigned to this dynamicCtrl property?
            $scope.dynamicCtrl = function($scope) {
                $scope.result = 'not working yet';
            };

            //eg:
            //$scope.dynamicCtrl = resolveCtrl('InnerCtrl');                                               
        }
    ])

    .controller('InnerCtrl', ['$scope', 'service',
        function($scope, service) {
            $scope.result = service.getMessage();
        }
    ])

   .factory('service', function() {
       return {
           getMessage:  function() { return 'working!'; }
       };
    });

I tried using the $injector service:

$scope.dynamicCtrl = $injector.get('InnerCtrl');

But this gives: "Unknown provider: InnerCtrlProvider <- InnerCtrl"

I also thought about using the $controller service:

$scope.dynamicCtrl = $controller('InnerCtrl', {} /* don't want to hard code dependencies */);

But this gives me "Unknown provider: $scopeProvider <- $scope". I know I could create a scope to pass in, but I feel that angular should be automatically resolving the scope and service dependencies for me.

How do I resolve a controller function from its name as a string, together with its dependencies, so it can be assigned to a scope variable?

like image 461
Mike Chamberlain Avatar asked Nov 01 '22 07:11

Mike Chamberlain


1 Answers

I was looking for the same thing and now after few hours finally it works:

You can use the $controller - service, but as you noticed, you need to create the scope on your own:

$controller('InnerCtrl', { $scope: $scope.$new() } );

Don't worry, all the other variables will be injected properly, but Angular isn't able to create the new scope on it's own. If you want to add the controller inside your HTML, it's a bit more complicated, you need to have a function in $scope which exposes the constructor of the controller:

$scope.InnerCtrl = function() {
    return $controller('InnerCtrl', { $scope: $scope.$new() }).constructor;
}

In HTML you can afterwards use it as always: <ANY ng-controller="InnerCtrl"></ANY>

I wrote a post about it with some additional details, but this is the main to solve the problem for you.

like image 187
peter Avatar answered Nov 12 '22 13:11

peter