Angular指令修改范围

时间:2014-12-14 14:26:58

标签: angularjs angularjs-directive

基本上我有2个指令:

  • 雷达图表(创建图表的通用指令)
  • 用户雷达图(使用雷达图表,不那么抽象)

radar-chart指令由以下实例化:

<radar-chart data="" labels="" options="" colours=""></radar-chart>

user-radar-chart指令由以下实例化:

<user-radar-chart preseverence="20" motivation="39"></user-radar-chart>

现在user-radar-chart应该使用radar-chart指令,但是使用一组固定的标签,颜色和选项,只有数据应该不同。

我该怎么做?

这就是我的尝试:

angular
    .module('myApp')
    .directive('userRadarChart', function () {
        return {
            restrict: 'E',
            template: '<canvas class="chart radar-chart" data="{{data}}" labels="{{labels}}" options="{{options}}" colours="{{colours}}"></canvas>',
            scope: {
                motivation: '@',
                preseverence: '@'
            },
            link: function ($scope, $element, $attrs) {
                $scope.data = [$attrs.motivation, $attrs.preseverence];
                $scope.labels = ['Motivation', 'Preseverence'],
                $scope.options = {};
                $scope.colours = ['Yellow'];
            }
        }
    })

2 个答案:

答案 0 :(得分:1)

当您说要使用<canvas>时,我不确定您在模板中使用<radar-chart>的原因,但我猜这是问题

Angular中没有指令的抽象。您可以将继承用于指令的控制器,但链接函数和指令不能被抽象。

您可以在模板中使用其他Angular指令作为指令,我认为这是您所缺少的。

angular
    .module('myApp')
    .directive('userRadarChart', function () {
        return {
            restrict: 'E',
            template: '<radar-chart data="{{data}}" labels="[\'Motivation\', \'Perseverance\']" options="{}" colours="[\'Yellow\']"></radar-chart>',
            scope: {
                motivation: '@',
                perseverance: '@'
            },
            link: function ($scope, $element, $attrs) {
                $scope.$watchGroup(['motivation','perseverance'],function(values) {
                    $scope.data = values;
                });
            }
    }
});

请注意,您应尽可能尝试使用观察者。如果激励和毅力的值与Angular表达式绑定,那么如果图表发生变化,图表将不会更新。

使用$scope.$watchGroup只要它们发生更改,就会使用值数组执行回调函数。使用@为范围分配属性时,它们已存在于范围中。因此,您不应该使用$attrs.motivation来访问它们。

我将静态参数移动到模板中。尝试在模板中保留样式和显示,并在代码中保留业务逻辑。使维护更容易。

答案 1 :(得分:1)

有几种不同的方法可以做到这一点。最简单的(我认为你用你的例子得到的)方法是让user-radar-chart的模板创建一个radar-chart指令:

此示例显示userRadarChart只是一个预设有color选项的雷达图表。

.directive('radarChart', function() {

  return {
    restrict: 'E',
    template: "<span>I am a {{color}} radar chart, with data:</span>\
               <pre>{{ data | json }}</pre>",
    scope: {
      data: "=",
      color: '@'
    },

    link: function (scope, element){
      element.css('background-color', scope.color); 
    }
  }
})

.directive('userRadarChart', function() {
  return {
    restrict: 'E',
    scope: { data: "=" },
    template: '<radar-chart data="data" color="green"></radar-chart>'
  }
});

angular.module('myApp', [])

.controller('MyController', function () {
  this.data1 = {
    foo: 'bar'
  }
  this.data2 = {
    dog: 'bone' 
  }
})

.directive('radarChart', function() {

  return {
    restrict: 'E',
    template: "<span>I am a {{color}} radar chart, with data:</span>\
               <pre>{{ data | json }}</pre>",
    scope: {
      data: "=",
      color: '@'
    },
  
    link: function (scope, element){
      element.css('background-color', scope.color); 
    }
  }
})

.directive('userRadarChart', function() {
  return {
    restrict: 'E',
    scope: { data: "=" },
    template: '<radar-chart data="data" color="green"></radar-chart>'
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.6/angular.min.js"></script>

<div ng-app="myApp">
  <div ng-controller="MyController as ctrl">
    <radar-chart color="red" data="ctrl.data1"></radar-chart>
    <user-radar-chart data="ctrl.data2"></user-radar-chart>
  </div>
</div>

注意上述观察者不是因为我们使用=所以data值正在利用angular的内置以双向数据绑定。

另一种选择是将user-radar-chart设置存储在radar-chart指令中,并在type上设置radar-chart属性,以便为您配置图表:

.directive('radarChart', function() {

  return {
    restrict: 'E',
    scope: {
      data: "=",
      color: '@'
    },

    link: function (scope, element, attrs){
      if (attrs.type === "user")
        // define user-radar-chart settings here.
        scope.color = 'green';
      element.css('background-color', scope.color);

    }
  }
});

还有很多方法可以做到这一点,但是如果您制作的子图章真的只​​是更改设置那么简单,我认为上述方法之一就是它应该如何完成 - 保持简单。