$scope.$emit/$broadcast 在 angular JS 中的自定义指令通信中不起作用
$scope.$emit/$broadcast not working in Custom Directive Communication in angular JS
我正在使用 HighCharts 来表示 堆积条形图 以及 折线图 。我的要求是 onClick 的堆积条形图 折线图应显示对应于 clicked.I 部分使用 $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);
}
};
});
好的。您有两个同名的指令(图表)。这个答案假设第二个实际上应该是 linechart
图表和折线图是兄弟。因此,当您从图表中 $broadcast 一个事件时,它没有 children,也没有人听到它。
同样,如果您从图表中 $emit 和事件,那么它将被发射到 parent 作用域 (MainCtrl),然后在层次结构中向上到达 $rootScope。它永远不会到达线图
当您使用 $scope.$parent.$broadcast 时,您是在告诉 MainCtrl 将事件广播到它的 children,它恰好是图表和折线图,所以它起作用了。
长话短说 - angular 在这里按预期工作。
与浏览器事件不同,angular 事件不会冒泡然后又上升。他们是一种方式。
您可以让 MainCtrl 监听该事件,然后 re-broadcast 它:
在 MainCtrl 中:
$scope.$on('HIGH_CHART....', function() {
//rebroadcast to children
var args = Array.prototype.shift.apply(arguments);
$scope.$broadcast('HIGH_CHART.....', args )
};
(或类似的东西。您必须从参数中删除第一个元素,然后使用其余参数调用 broadcast - 在问题范围之外)。
我正在使用 HighCharts 来表示 堆积条形图 以及 折线图 。我的要求是 onClick 的堆积条形图 折线图应显示对应于 clicked.I 部分使用 $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);
}
};
});
好的。您有两个同名的指令(图表)。这个答案假设第二个实际上应该是 linechart
图表和折线图是兄弟。因此,当您从图表中 $broadcast 一个事件时,它没有 children,也没有人听到它。
同样,如果您从图表中 $emit 和事件,那么它将被发射到 parent 作用域 (MainCtrl),然后在层次结构中向上到达 $rootScope。它永远不会到达线图
当您使用 $scope.$parent.$broadcast 时,您是在告诉 MainCtrl 将事件广播到它的 children,它恰好是图表和折线图,所以它起作用了。
长话短说 - angular 在这里按预期工作。
与浏览器事件不同,angular 事件不会冒泡然后又上升。他们是一种方式。
您可以让 MainCtrl 监听该事件,然后 re-broadcast 它:
在 MainCtrl 中:
$scope.$on('HIGH_CHART....', function() {
//rebroadcast to children
var args = Array.prototype.shift.apply(arguments);
$scope.$broadcast('HIGH_CHART.....', args )
};
(或类似的东西。您必须从参数中删除第一个元素,然后使用其余参数调用 broadcast - 在问题范围之外)。