我在 Angular Directive(指令)中包装 D3 svg 图像。当用户单击该 D3 图像时,我想在 Controller 中将一个变量设置为 true,以便 ng-show 然后显示另一个 D3 图像。
我所做的是向 D3 图像添加一个 .on("click")
函数,并在该函数中使用 $rootScope.$emit()
发送一个事件。在第二张图片的 Controller 中,我有一个 $rootScope.$on()
来控制事件并将 ng-show 的变量设置为 true。
这种方法行不通。我已经测试了代码以确保事件被正确发出和捕获,但是 ng-show 没有显示第二个 D3 图像。
这是为什么?
我创建了一个小插件来说明我正在尝试做什么。 http://plnkr.co/edit/FnqeAF9kVXxdUdOzT5to .
Controller 代码如下:
function CircleCtrl($rootScope) {
this.render = function(element, attrs) {
var svg = d3.select(element[0]).append("svg")
.attr("width", 200)
.attr("height", 200);
var circle = svg.append("circle")
.attr("cx", 30)
.attr("cy", 30)
.attr("r", 20);
circle.on("click", function(d,i) {
var data = {val0: "zero", val1: "one"};
$rootScope.$emit("Circle Clicked", data);
});
};
}
function SquareCtrl($rootScope) {
this.showSquare = false;
$rootScope.$on("Circle Clicked", function(event, data) {
this.showSquare = true;
})
this.render = function(element, attrs) {
var svg = d3.select(element[0]).append("svg")
.attr("width", 200)
.attr("height", 200);
var rectangle = svg.append("rect")
.attr("x", 10)
.attr("y", 10)
.attr("width", 50)
.attr("height", 100);
};
}
angular.module("AngularD3Example")
.controller("CircleCtrl", ["$rootScope", CircleCtrl])
.controller("SquareCtrl", ["$rootScope", SquareCtrl]);
最佳答案
从 Angular 上下文外部更改 Angular 的范围不会更新范围变量和绑定(bind),因为它不会运行 Angular 的摘要循环。在这里,您正在使用事件 click
到 Angular 上下文。
您需要在 $rootScope
范围内运行 $apply()
方法来运行摘要循环将有效地更新绑定(bind)。
代码
circle.on("click", function(d,i) {
var data = {val0: "zero", val1: "one"};
$rootScope.$emit("Circle Clicked", data);
$rootScope.$apply();
});
另一件事是你需要确保在使用 this
关键字时你应该用一些变量在外面声明它然后使用它
Controller
function SquareCtrl($rootScope) {
var square = this; //made this as a global can be accessible through `square` variable
square.showSquare = false; //<-- as changed this to square
$rootScope.$on("Circle Clicked", function(event, data) {
square.showSquare = true; //<-- as changed this to square
})
//....
}
您还必须注销 $rootScope 监听器,否则会导致应用程序内存泄漏。 .on 监听器的返回值实际上是你在$destroy 事件发生时使用的函数,以实现此目的
// Start Custom Events
var cleanApplyEvent = $rootScope.$on('submitChanges', function(event, args) {
self.applyData(args);
})
// manually unregister rootScope listeners to avoid memory leaks
$scope.$on('$destroy', function(){
cleanApplyEvent();
})
// End Custom Events
Note
Its bad practice to have DOM manipulation inside controller, you should create a directive an do DOM manipulation and events should be handle from there
关于javascript - 如何通过 D3 单击事件让 $rootScope.$emit() 和 ng-show 协同工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32257227/