admin管理员组

文章数量:1391974

Acpanying plunker (in coffeescript, but javascript below)

I cannot get an attribute-scoped variable (@) to bind in a directive.

Here's the directive code:

app.directive('myDirective', [
  function() {

    var pileFn, config, linkFn;

    linkFn = function($scope, element, attr) {
      return alert("foo: " + $scope.foo);
    };

    pileFn = function() {
      return linkFn;
    };

    return config = {
      pile: pileFn,
      scope: {
        foo: '@myDirectiveFoo'
      }
    };
  }
]);

and the HTML:

<span my-directive my-directive-foo="bar"></span>

I'd expect the value that's alerted would be 'bar', but instead it's undefined. What am I missing?

Acpanying plunker (in coffeescript, but javascript below)

I cannot get an attribute-scoped variable (@) to bind in a directive.

Here's the directive code:

app.directive('myDirective', [
  function() {

    var pileFn, config, linkFn;

    linkFn = function($scope, element, attr) {
      return alert("foo: " + $scope.foo);
    };

    pileFn = function() {
      return linkFn;
    };

    return config = {
      pile: pileFn,
      scope: {
        foo: '@myDirectiveFoo'
      }
    };
  }
]);

and the HTML:

<span my-directive my-directive-foo="bar"></span>

I'd expect the value that's alerted would be 'bar', but instead it's undefined. What am I missing?

Share Improve this question asked Jan 23, 2014 at 14:12 Roy TrueloveRoy Truelove 22.5k21 gold badges116 silver badges154 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 7

Short answer: to get the expected value foo in your link function you have to observe the attribute:

attr.$observer('myDirectiveFoo', function(value){
    console.log(value);
    console.log($scope.foo);
});

both console outputs will give you the expected bar value. Why? the attribute value must be interpolated and this will happen after the link function was called.

Long answer: The documentation stated for the attr object that is passed to the link function:

Use $observe to observe the value changes of attributes that contain interpolation (e.g. src="{{bar}}"). Not only is this very efficient but it's also the only way to easily get the actual value because during the linking phase the interpolation hasn't been evaluated yet and so the value is at this time set to undefined.

Let's have a look at a modified version of you example. It shows also the differences between = und @ scoping.

This is our html:

<body ng-controller="MainCtrl">
   <span  my-directive my-directive-foo="hello {{name}}" my-directive-bar="name" ></span>
 </body>

This is the controller:

app.controller('MainCtrl', function($scope, $timeout, $interpolate){
  $scope.name = 'roy';
  $timeout(function(){
    $scope.name = 'michael';
  },4000);
});

As you can see, we have a name property that will change from roy to michael after 4 seconds.

This is the directive:

app.directive('myDirective', function() {
    return {
      scope: {
        foo: '@myDirectiveFoo',
        bar: '=myDirectiveBar'
      },
      link: function ($scope, iElement, iAttrs, controller) {
          console.log('link foo: '+$scope.foo); 
          console.log('link bar: '+$scope.bar);
          iAttrs.$observe('myDirectiveFoo',function(value){
              console.log('link observed foo: '+$scope.foo, value);    
          }); 
          $scope.$watch('bar', function(newValue, oldValue){
              console.log('watch', oldValue, newValue);
          });
          console.log('link done'); 
      },
      controller: function($scope){ 
          console.log('controller foo:'+$scope.foo);
          console.log('controller bar:'+$scope.bar);
      }
  };
});

We have two isolated scope properties. foo configured as one-way-binding and bar configured as two-way-binding. In the controller output we will see, that the two-way-binding ($scope.bar) is available immediately and the one-way-binding ($scope.foo) is not. In the link function we have the same result. If the linking is done we will see that the observer and the watcher will fire with the current (and expected) values. The observer and the watcher will fire again if the name property changed their value after 4 seconds.

see it live @ PLUNKR

本文标签: javascriptAngularJs Directiveattribute scoped variable not bindingStack Overflow