简体   繁体   中英

Can't access attr data in angular custom directive link function

I'm trying to access attr data defined by a controller in a custom directive's link function.

Here is some simple angular markup:

<div class='barChart'>
  {{vm.totals}}
  <bar-chart chart-data='vm.totals'></bar-chart
</div>

This is the directive defintion:

angular
    .module('app')
    .directive('barChart', [Callback])

function Callback() {
    return {
      restrict: 'E',
      replace: false,
      scope: {data: '=chartData'},
      link: (scope, el, attrs) => {
        console.log(scope);
        console.log(el);
        console.log(attrs.chartData);
      }
    }
}

When I log scope, I can see the data array in this object as expected, heres a picture: 在此处输入图片说明

As you can see the data is the 10 item array at the bottom. The array also shows up in the browser, so the data is there. However, as soon as I change the console.log to log that property:

console.log(scope.data)

The value that gets printed is undefined. I'm trying to access the data in the link function so that I can use d3 to create a visualization. The data is there, but it's undefined as soon as I call .data on scope. Any ideas?

Use $watch to log the data:

angular
    .module('app')
    .directive('barChart', [Callback])

function Callback() {
    return {
      restrict: 'E',
      replace: false,
      scope: {data: '=chartData'},
      link: (scope, el, attrs) => {
        console.log(scope);
        console.log(el);
        console.log(attrs.chartData);
        //USE $watch
        scope.$watch("data", function(value) {
          console.log(value);
        });
      }
    }
}

you can access vm.totals as scope variable but passed as attribute:

scope: {
  chartData: '='  //@ reads the attribute value
}

And in your html:

<bar-chart chart-data='vm.totals'></bar-chart>

Now in link function you can access it:

console.log(scope.chartData);

Note that this is one way binding, so if you need two way you need to use = instead.

Update:

If you are using async call you need to use two way binding or watch for the changes in your link function:

scope.$watch('chartData', function(newVal) {
    if(newVal) {  console.log(scope.chartData) }
}, true);

Note that since it is an array it is better to use collection watch (true as the last arg).

use @ in the link function to have one way binding to the controller.

 angular .module('app', []) .controller('ctrl', function($scope){$scope.totals="1234";}) .directive('barChart', [Callback]) function Callback() { return { restrict: 'E', replace: false, scope: {data: '@'}, link: function(scope, el, attrs) { console.log(attrs.chartData); } } }
 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <div ng-app="app" ng-controller="ctrl"> <div class='barChart'> {{totals}} <bar-chart chart-data='{{totals}}'></bar-chart> </div> </div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM