在角度js中,如何将数据从父控制器传递到子控制器?

时间:2015-07-04 22:54:46

标签: javascript angularjs

我有一个小部件,我想在一个页面上反复使用。它有自己的控制器。问题是它需要一个数据来操作(基本上是一个键),每个键都包含在父控制器中。

这是一个例子(显然是错误的)

http://plnkr.co/edit/VajgOr1LqpLDnbEJcvor?p=preview

脚本:

angular.module('myApp', [])
  .controller('ParentCtrl', ['$scope',
    function($scope) {
      $scope.keyForChartABC = "somekey1";
      $scope.keyForChartXYZ = "somekey2";
      $scope.keyForChartLALA = "somekey3";

    }
  ])
  .controller('ChartCtrl', ['$scope',
    function($scope) {
      //todo: have $scope.key assigned from parent somehow

      //not shown:  use $scope.key to pull data and format chart data
    }
  ])

指数:   

    <!-- ng-init like this is quite wrong -->
    <div    ng-init="key = keyForChartABC"
            ng-include="'chartwidget.html'"></div>
    <hr>
    <div    ng-init="key = keyForChartXYZ"
            ng-include="'chartwidget.html'"></div>
    <hr>
    <div    ng-init="key = keyForChartLALA"
            ng-include="'chartwidget.html'"></div>

chartwidget:

<div ng-controller="ChartCtrl">
    <p>Drawing chart for data: {{key}}</p>
    <p>some chart directive here</p>
</div>

正如你在plunker中看到的那样,我在这里尝试使用ng-init并不起作用 - 所有子控制器的键最终都具有相同的值。

我已经使用ng-repeat和父数据中的一组数据,不知何故$ index将每个子项设置为正确的索引并保留一个值。但是我想在这种情况下避免使用ng-repeat,这样我就可以更好地控制布局。

1 个答案:

答案 0 :(得分:7)

创建可重复使用的小部件正是指令的目的。您可以创建一个非常容易处理窗口小部件输出的指令。

我分叉你的plunker并对其进行修改以将其更改为使用指令。

以下是一些亮点:

首先,您的模板不再需要在其中定义的控制器。

<div>
    <p>Drawing chart for data: {{key}}</p>
    <p>some chart directive here</p>
</div>

接下来,定义了一个指令,其中包含一个隔离范围,该范围对于指令的每个实例都是唯一的:

.directive('chartWidget', function(){
    return {
      restrict: 'E',
      scope: {
        key: '='
      },
      templateUrl : 'chartwidget.html'
    }
})

最后,该指令在HTML中声明。请注意JavaScript中指令的camel-case名称,但HTML中的带连字符的名称:

<div>
    <chart-widget key="keyForChartABC"></chart-widget>
    <hr>
    <chart-widget key="keyForChartXYZ"></chart-widget>
    <hr>
    <chart-widget key="keyForChartLALA"></chart-widget>
</div>

修改

我更新了plunker以显示将指令属性绑定到内部控制器。此方法使用ControllerAs语法定义控制器,并将指令的作用域绑定到控制器作用域。

相关变化:

.directive('chartWidget', function(){
    return {
      restrict: 'E',
      scope: {
        key: '='
      },
      templateUrl : 'chartwidget.html',
      controller: 'chartWidgetController',
      controllerAs: 'ctrl',
      bindToController: true
    }
  })
  .controller('chartWidgetController', function(){
    console.log(this.key);
  })

对模板进行一些小改动以支持ControllerAs:

<div>
    <p>Drawing chart for data: {{ctrl.key}}</p>
    <p>some chart directive here</p>
</div>

请注意,尝试在模板中使用ng-controller=将导致模板与为指令创建的范围对象具有不同的范围对象,并且控制器将无法访问指令中定义的属性。

另请注意,bindToController是角度1.3.x或更高的功能。在角度1.2.x或更早版本中,您唯一的选择是使用$scope.$watch来监控隔离范围以进行更改。