1

Although this question has been asked before, it is not working for me. The controller variable "myVar" is set before the link function is called. And according to docs and other posts myVar should be available in the link function, but it is not. In fact the link scope contains a parent controller reference, but no reference to its own controller??? Any ideas?

angular.module('app.main')
    .directive('myWidget', MyWidget)
    .controller('MyWidgetCtrl', MyWidgetCtrl)

function MyWidget() {
    return {
        restrict: 'E',
        templateUrl: 'my-widget-tmpl.html',
        controller: MyWidgetCtrl,
        link: function (scope, element, attrs) {
            var test = false;
            test = myVar;  // doesn't work
            test = scope.myVar;  // doesn't work
            test = scope.vm.myVar;  // doesn't work
        }
    };
}

MyWidgetCtrl.$inject = ['$scope'];
function MyWidgetCtrl($scope) {
    var vm = this;
    vm.myVar= true;
}

2 Answers 2

3

You're mixing two methods here. In your controller, you're putting things on the controller instance. Which will work fine, as long as you specify bindToController: true in your directive definition. This is considered best practice now anyways, for several reasons.

The problem in your link function is that you're expecting a variable to be on the scope, but it isn't. It's on the controller, which is on the scope. You. However, the forth injectable of the link function is the directives controller, so you can access it like so:

link: function(scope, element, attrs, ctrl) {
    var test = false;
    test = ctrl.myVar;
}

The only hiccup in this is if you require other directives, then you have to also reqire your own directives controller (I think), and instead of a single controller, you'll be given an array of controllers in your link function instead of just one. If you've never used require, don't worry about what I just said, but keep it in the back of your mind in case you ever want to use require.

EDIT: The above information is still pertinent, and probably good for you to read, but it just occurred to me that all you really have to do to make your code work is add bindToController: true and controllerAs: 'vm'. That's the only two things you're missing.

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

1 Comment

Yes that worked for me, using your suggestion in the EDIT, thx
1

You should bind your variable on the MyWidgetCtrl's $scope:

MyWidgetCtrl.$inject = ['$scope'];
function MyWidgetCtrl($scope) {
    $scope.myVar = true;
}

Otherwise you should use the bindToController approach, to skip the usage of the $scope.

8 Comments

If he wants to access his controller in link function though, he needs to use bindToController and controllerAs to name what variable it will bound to on scope, right?
Then the directive's controller object can be accessed from the fourth attribute in the link function ctrls, as var hisCtrl = ctrls[0];
Yes, but that becomes more complicated if he uses the require field on the DDO. I think it's easier to just name it and put it on scope. It's what's happening anyways, I believe.
Well you should avoid the $scope object and anything added on it. It's completely dropped in Angular 1.6 and does not exists in 2.0.
But that's exactly what bindToController is doing. It's just putting the controller on the $scope. The only reason you can access vm in the controller, for example, is because the controller is on the scope as vm. Right?
|

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.