Tuizi
Tuizi

Reputation: 1673

Access require controller in a directive controller

app.directive('mainCtrl', function () {
    return {
        controller: function () {
            this.funcA = function(){}
        }
    };
});

app.directive('addProduct', function () {
    return {
        restrict: 'E',
        require: '^mainCtrl',
        link: function (scope, lElement, attrs, mainCtrl) {
            mainCtrl.funcA()
        }
    };
});

I don't want to use the link method but the controller method. Is there a way to get the mainCtrl in the controller method of the directive addProduct.

something like:

app.directive('addProduct', function () {
    return {
        restrict: 'E',
        require: '^mainCtrl',
        controller: function (scope, mainCtrl) {
            mainCtrl.funcA()
        }
    };
});

Upvotes: 4

Views: 906

Answers (4)

AquaFlaskBrem
AquaFlaskBrem

Reputation: 101

Pass the controller to the scope on the link function then accessing the scope on controller. Like this:

app.directive('mainCtrl', function () {
       return {
            controller: function () {
                this.funcA = function(){}
            }
        };
    });

app.directive('addProduct', function () {
    return {
        restrict: 'E',
        require: '^mainCtrl',
        link: function (scope, lElement, attrs, mainCtrl) {
            scope.ctrl=mainCtrl;
        },controller:function($scope){
            $scope.ctrl.funcA();
        }
    };
});

Upvotes: 0

cdauth
cdauth

Reputation: 7558

Since AngularJS 1.5, you can use the $onInit lifecycle hook of the controller. As written in the documentation of require, when defining require as an object and setting bindToController to true, the required controllers are added to the controller as properties after the controller has been constructed, but before the $onInit method is run. So the code would look like this:

app.directive('mainCtrl', function () {
    return {
        controller: function () {
            this.funcA = function(){}
        }
    };
});

app.directive('addProduct', function () {
    return {
        restrict: 'E',
        require: {
            myParentController: '^mainCtrl'
        },
        bindToController: true,
        controller: function ($scope) {
            this.$onInit = function() {
                this.myParentController.funcA();
            };
        }
    };
});

Upvotes: 1

Tuizi
Tuizi

Reputation: 1673

Here is my solution:

app.directive('mainCtrl', function () {
    return {
        controllerAs: 'main',
        controller: function () {
            this.funcA = function(){}
        }
    };
});

app.directive('addProduct', function () {
    return {
        restrict: 'E',
        require: '^mainCtrl',
        controller: function ($scope) {
            $scope.main.funcA();
        }
    };
});

Upvotes: 0

New Dev
New Dev

Reputation: 49590

You'd still need to use the link function because the controllers are injected there. What you could, however, is request your directive's own controller and then set the other required controller as its property:

app.directive('addProduct', function () {
    return {
        restrict: 'E',
        require: ['addProduct','^mainCtrl'],
        controller: function ($scope) {
            // this.mainCtrl is still not set here
            // this.mainCtrl.funcA(); // this will cause an error

            // but typically it is invoked in response to some event or function call
            $scope.doFuncA = function(){
               this.mainCtrl.funcA();
            }
        },
        link: function(scope, element, attrs, ctrls){
          var me = ctrls[0], mainCtrl = ctrls[1];
          me.mainCtrl = mainCtrl;
        }
    };
});

Upvotes: 4

Related Questions