最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - From an AngularJS controller, how do I resolve another controller function defined in the module (dynamic ng-contro

programmeradmin0浏览0评论

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
 |  Show 1 more ment

2 Answers 2

Reset to default 8

You 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>

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论