【问题标题】:$scope.$emit/$broadcast not working in Custom Directive Communication in angular JS$scope.$emit/$broadcast 在 Angular JS 中的自定义指令通信中不起作用
【发布时间】:2015-02-18 02:13:02
【问题描述】:

我正在使用 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);
    }
};
});

【问题讨论】:

  • 什么组件在监听事件?
  • @JoeEnzminger 我没有收到您的问题。请详细说明...使其更清楚...Highchart 正在向折线图发送事件...
  • 我没有看到正在监听 HIGH_CHART_CLICKED 事件的组件......即 $scope.$on('HIGH_CHART_CLICKED', function()......
  • 非常抱歉...复制粘贴错误。不过,我现在已经更正了。
  • @JoeEnzminger..让我知道您是否需要更多信息...请澄清这一点为什么会发生这种情况...

标签: angularjs angularjs-directive angularjs-scope


【解决方案1】:

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

chart 和 linechart 是同级的。因此,当您从图表中 $broadcast 一个事件时,它没有孩子,也没有人听到它。

同样,如果您从图表中 $emit 和事件,那么它将被发射到父范围 (MainCtrl),然后在层次结构上上升到 $rootScope。它永远不会到达折线图

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

长话短说 - Angular 在这里按预期工作。

与浏览器事件不同,角度事件不会冒泡然后备份。它们是一种方式。

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

在 MainCtrl 中:

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

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

【讨论】:

  • 是的..现在理解越来越清楚了,你说得对,第二个指令是 lineChart....感谢您提出另一种方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-27
  • 1970-01-01
  • 2020-10-16
  • 2017-02-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多