1

Say I have two instances of the same controller "ControllerA" instantiated using ng-controller with as syntax inside of a wrapping controller:

<div ng-contrller="MainController">
    <div ng-controller="ControllerA as Ctrl1"></div>
    <div ng-controller="ControllerA as Ctrl2"></div>
</div>

Now what i want to achieve is that i can call something like Ctrl1.controllerFunction() inside of the MainController. Normally I would use $broadcast and $on to achieve a similiar behaviour when there would not be two instances of the same controller, so i can't use it here. I also don't want to use preventDefault on the event object of the $broadcast because it would get too messy.

2
  • 1
    I can't think of a use case where you need to instantiate the same controller twice or have a parent controller depend on a 'child' controller. It sounds like you need to rethink your page using directives and components. Commented Jul 5, 2016 at 9:26
  • It's somehow complicated, yes. My use case is that I have a page consisting of different "views" (using ng-show currently). In one of that view the controller is placed in a modal dialog while on the other it is placed embedded on the page. Now when I want to load data within the controller (always in just one instance), I can't get that managed. Using $broadcast, both controllers will get active. I want to call a certain controller depending on the method of the parent controller. Commented Jul 5, 2016 at 9:47

1 Answer 1

1

There isn't an easy way to do what you are asking. Ctrl1 isn't defined in the scope of MainController, it's in a sub-scope. Ctrl1 and Ctrl2 aren't even in the same scopes as each other so there's no real reason why you need to use different names. Also you could have ng-repeat or ng-if creating and destroying ControllerA instances so the lifetimes may be shorter than for MainController.

A better way to handle this would be to invert the responsiblities and make ControllerA instances register with MainController when created and de-register when destroyed. If you use controllerAs syntax also for MainController then it is easy for the child controllers to call methods on MainController.

<div ng-controller="MainController as Main">
    <div ng-controller="ControllerA as Ctrl1" ng-init="Ctrl1.init('Ctrl1')"></div>
    <div ng-controller="ControllerA as Ctrl2" ng-init="Ctrl2.init('Ctrl2')"></div>
</div>

function ControllerA($scope) {
    const vm = this;
    vm.init = function(name) {
        $scope.Main.register(name, vm);
        $scope.$on('$destroy', function() {
            $scope.Main.deregister(name);
        });
    }
}

You then write suitable register and deregister functions in MainController to keep track of the child controllers. Something like:

function MainController() {
    const vm = this;
    const children = {};
    vm.register = function(name, vm) { children[name] = vm; }
    vm.deregister = function(name) { delete children[name]; }

   // ... and now you can do 
    if (children.Ctrl1) children.Ctrl1.controllerFunction();
}

You might instead put the init method in MainController but that would make de-registration difficult as you need the child scope.

Sign up to request clarification or add additional context in comments.

2 Comments

Am I guessing right that i could use $scope.Ctrl1.method() in the MainController? I am not familiar with that register and deregister method nor can I find anything in the docs about that.
No, MainController's scope cannot reference Ctrl1 as that is in a child scope, but the child controllers can reference the parent scopes. The intention is that you write register and deregister functions to keep track of the child scopes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.