Inzajt
Inzajt

Reputation: 135

Access $scope from isolated directive

I want to change a $scope variable from inside an isolated directive, how is this possible?

I have tried using the '@, =, &' syntax in the directive scope but cannot get it to work.

This is my simplified code

JS

app.controller('testCtrl', function($scope) {
    $scope.hello = 'hello';
}

app.directive('testDirective', function() {
    return {
        restrict: 'E',
        template: '<div>{{text}}</div>',
        scope: {},
        link: function(scope, element) {
            scope.text = 'this is my text';
            scope.hello = 'hello world!';
        }
    };
});

HTML

<body>
    {{ hello }}
    <test-directive />
</body>

This is the output i want

hello world!
this is my text

Upvotes: 1

Views: 87

Answers (3)

ilmgb
ilmgb

Reputation: 770

Here's what was missing:

  1. ng-controller was not defined
  2. @ means passing the attribute as a string, = means binding the property to a property from the parent's scope (which is what we need here) and & means passing in a function from the parents scope to be called later.
  3. when the directive is called "testDirective" it looks in the HTML as follows:<test-directive></test-directive> as camel cases in JS need to be seperated by "-" in HTML.

<body ng-controller="testCtrl"> {{ hello }} <test-directive hello-from-parent="hello"></test-directive> </body>

app.directive('testDirective', function() { return { restrict: 'E', scope: { hello: "=helloFromParent" }, template: '<div>{{text}}</div>', link: function(scope, element, attrs) { scope.text = 'this is my text'; scope.hello = 'hello world'; } } });

I set up a working plnkr here

Upvotes: 0

Christian Yang
Christian Yang

Reputation: 472

You can set a require option on the directive and specify a parent controller. This will pass the controller to your link function as the last argument:

app.directive('testDirective', function() {
    return {
        restrict: 'E',
        template: '<div>{{text}}</div>',
        require: '^testCtrl',
        scope: {},
        link: function(scope, element, attrs, testCtrl) {
            scope.text = 'this is my text';
            testCtrl.setHello('hello world!');
        }
    };
});

Note you have to create this testCtrl.setHello() method on your controller. This is because you get the controller itself, not its injected scope:

app.controller('testCtrl', function($scope) {
    $scope.hello = 'hello';
    this.setHello = function(newHello) {
      $scope.hello = newHello;
    }
}

Also, if you don't really care about strictly enforcing the controller dependency, you can directly access scope.$parent.$parent.hello from your directive.

Upvotes: 2

Michael Kang
Michael Kang

Reputation: 52837

In HTML, the directive must be in snake-case:

<test-directive />

In your script, the directive must be defined in camel case:

app.directive('testDirective', function() {
});

Also, add the ngController directive:

<body ng-controller="testCtrl>
</body>

Upvotes: 0

Related Questions