$ scope。$ emit / $ broadcast在角度JS中的自定义指令通信中不起作用

时间:2015-02-17 17:23:58

标签: angularjs angularjs-directive angularjs-scope

我使用HighCharts代表堆积条形图以及折线图。我的要求是 onClick 堆积条形图折线图应该显示对应于点击的部分。我使用 $ broadcast $ on 来实现它。当我在 highchart.js 中使用 $ emit 时,它无效,但是当我使用 $ broadcast $ scope时。$ parent 。$ broadcast 它有效。有人可以让我知道为什么事件的向上流动正在发挥作用,向下流动它不起作用。我的两个指令都是针对同一个控制器。

在我的情况下,为什么 $ scope。$ emit $ scope。$ broadcast 单独工作?

index.html

    <div ng-controller='MainCtrl'>
      <chart values='basicAreaChart' id="container" technology="3G" url="../json/HighCharts.json"></chart>

      <linechart values='basicLineChart' id="container2" technology="LTE" click='clicked'></linechart>
    </div>

controller.js

  angular.module('chartsExample', ['lineChart','highchart']).controller('MainCtrl',
    [ '$scope', '$http', function($scope, $http) {
   } ]);

highchart.js

'use strict';

angular.module('highchart', []).directive('chart', function() {
return {
    restrict: 'E',
    scope: {
        chartData: "=values"
     },
    transclude: true,
    replace: true,
    controller:function($scope,$element,$attrs,$http){
        $http.get($attrs.url).success(function(data) {
            $scope.chartData = data;
            console.log('technology='+$attrs.technology+' '+$scope.a);
        });
    },
    link: function($scope, $element, $attrs,$rootScope) {
         '+$attrs.type);

        $scope.$watch('chartData', function(value) {
            if (!value){
                //console.log('In return');
                return;
            }
          // Initiate the chartData.chart if it doesn't exist yet
           $scope.chartData.chart = $scope.chartData.chart ;
            $scope.chartData.chart.renderTo =$attrs.id

            $scope.chartData.chart.events = {
                click : function() {
                    console.log('Chart clicked '+$scope.isClicked+' '+$scope.a);
                    $scope.click="false";

                    $scope.$parent.$broadcast('HIGH_CHART_CLICKED', 'clicked');
         //This works but $scope.$emit or $scope.$broadcast does'nt work???

                }
            };
            $scope.chartObj = new Highcharts.Chart($scope.chartData);
        },true);
    }
};
});

linechart.js

'use strict';

angular.module('highchart', []).directive('chart', function() {
return {
    restrict: 'E',
    scope: {
        linechartData : "=values"
     },
    transclude: true,
    replace: true,
    controller:function($scope,$element,$attrs,$http){
        $scope.$on('HIGH_CHART_CLICKED',function(e,data){
            console.log('Line chart Listening event');
            $http.get("../json/NewLineChart.json").success(function(data) {
                $scope.linechartData = data;
                console.log('this is from line chart');
            });
        });
    },
    link: function($scope, $element, $attrs,$rootScope) {
         '+$attrs.type);

        $scope.$watch('linechartData', function(value) {
            if (!value){
                //console.log('In return');
                return;
            }
          // Initiate the chartData.chart if it doesn't exist yet
           $scope.chartData.chart = $scope.chartData.chart ;
            $scope.chartData.chart.renderTo =$attrs.id
           }
            };
            $scope.chartObj = new Highcharts.Chart($scope.chartData);
        },true);
    }
};
});

1 个答案:

答案 0 :(得分:3)

确定。您有两个具有相同名称的指令(图表)。这个答案假设第二个实际上应该是线图

图表和折线图是兄弟姐妹。所以当你从图表广播一个事件时,它没有孩子,也没有人听到它。

同样,如果您从图表中发出$ emit和event,那么它将被发送到父作用域(MainCtrl),然后在层次结构上向$ rootScope发出。它永远不会到达线图

当你使用$ scope。$ parent。$ broadcast时,你告诉MainCtrl将事件广播给它的孩子,这恰好是图表和线图,所以它可以工作。

长话短说 - 角度正如预期的那样工作。

与浏览器事件不同,角度事件不会向下冒泡然后再进行备份。他们是单向的。

您可以让MainCtrl侦听该事件,然后重新广播它:

在MainCtrl中:

$scope.$on('HIGH_CHART....', function() {
    //rebroadcast to children
    var args = Array.prototype.shift.apply(arguments);
    $scope.$broadcast('HIGH_CHART.....', args )
};

(或类似的东西。你必须从参数中删除第一个元素,然后用剩余的参数调用广播 - 超出问题的范围)。