1

I can't set a scope variable inside my custom directive's controller.

See this plkr: http://plnkr.co/edit/KVGVxhgRHxkhCLytkLBv?p=preview

Link function prints the variable name but interpolator does not evaluate {{name}}. I set it in the controller of my custom directive with isolate scope. Still for some reason, scope variable does not persist. Is this behavior expected? If so what is the proper way to set scope variables?

Help is appreciated.

2 Answers 2

3

Import 'name' from your outside scope into your isolated scope using '=' binding:

// Code goes here
angular.module('test', [])
  .directive('nametag', function() {
    return {
      scope: { name: '='},
      controller: function($scope, $attrs, $log) {
        $scope.name = 'John Doe';
      },
      link: function(scope, elem, attrs) {
        // elem.text(scope.name);
      }
    };
  });

HTML:

<div ng-app="app" ng-init="name='james'>
    <nametag name="name"></nametag>
</div>

When you define an isolated scope for your directive (by specifying scope: {}) you create a private scope that does not prototypically inherit from the parent scope. You can think of an isolated scope as your directive's private sandbox.

Since your directive's scope is isolated, you need to import scope variables from parent scope into your isolated scope through attribute bindings. In this case we are establishing two-way binding between the parent scope variable 'name', and the directive's isolated scope variable with the same name.

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

3 Comments

Neat but this won't work in my case as I will need to reuse the same directive. My understanding is that AngularJS evaluates expression {{name}} bottom-up, in this case starting from isolate scope to its ancestry. Why would it not show the variable name that is already in directive's isolate scope?
That is not correct. What you are describing is resolving of scope variables using prototypical scope inheritance. In this case, your directive has an isolated scope. Scope inheritance rules do not apply. If you want to resolve {{name}} through scope inheritance, then use 'scope:true' in your directive definition.
I also want to mention that scope:true will create a new child scope, that relies on scope inheritance. scope:false will not create a new child scope, but it still inherits from the parent scope.
2

Your directive controller assigns the name to the isolated scope of the directive. So you have two possibilities:

  1. Remove the scope: {} from your directive to not create an isolated scope. While this works it is maybe not what you want as your directive modifies the outer scope.

  2. Add a template to your diective containing the <h1>Hello {{name}}</h1>. See this plunker.

Comments

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.