[英]Angular 2 D3 Event, Change Detection and Context
My Issue: I am using D3 in an Angular 2 component to draw SVGs on the screen. 我的问题:我在Angular 2组件中使用D3在屏幕上绘制SVG。 This works fine, however I want to attach events to the D3 produced SVGs and in that event call a method in my Angular 2 Component.
这工作正常,但我想将事件附加到D3生成的SVG,并在那个事件中调用我的Angular 2组件中的方法。 That method will take the Data provided by the D3 SVG and assign it to a variable in my Angular 2 Parent component.
该方法将获取D3 SVG提供的数据并将其分配给我的Angular 2 Parent组件中的变量。 That variable is an Input variable for my Child Angular 2 component.
该变量是我的Child Angular 2组件的Input变量。 I cannot currently call the Function in the Angular 2 Component from within the D3 event callback.
我目前无法在D3事件回调中调用Angular 2 Component中的Function。 The keyword "this" has a different context from within the callback than when using it within an Angular 2 component and thus I cannot get a reference to be able to call the function I want.
关键字“this”与回调内部具有不同的上下文,而不是在Angular 2组件中使用它,因此我无法获得能够调用我想要的函数的引用。
My Project: So I have an Angular 2 Project and I have 2 Components with a Parent - Child Relationship. 我的项目:所以我有一个Angular 2项目,我有2个组件,父子关系。 The D3 Canvas Component is the Parent and as you can see below I have a data-detail-panel contained within this component template.
D3 Canvas组件是Parent,如下所示,我在此组件模板中包含了一个data-detail-panel。 data-detail-component is powered by the Input Variable 'activeEntity' which I want to be populated based upon the D3 event when the SVG is hovered on.
data-detail-component由输入变量'activeEntity'提供支持,我希望在SVG悬停时根据D3事件填充它。
<div class="row">
<div class="col-xs-8 col-sm-8 col-md-8 col-lg-8">
<div id="d3-canvas-host"></div>
</div>
<div class="col-xs-4 col-sm-4 col-md-4 col-lg-4">
<data-detail-panel [activeEntity]="activeEntity"></data-detail-panel>
</div>
</div>
Now in the Angular 2 Component that initialises the D3 Graph and visualises the data this is how it is set up: 现在在Angular 2 Component中初始化D3 Graph并可视化数据,这就是它的设置方式:
import {
Component,
OnInit,
} from '@angular/core';
import {
DataDetailPanel
} from '../detailPanel';
import * as D3 from 'd3';
@Component({
template: require('./entitiesVisualisation.html'),
styles: [require('./entitiesVisualisation.css')],
directives: [DataDetailPanel],
})
export class EntitiesVisualisation {
activeEntity: any;
drawTopologyView(nodeContainer, entityData, colorRange: D3.scale.Linear < string, string > ) {
// Make sure that previous elements are cleared before redrawing
nodeContainer.selectAll('*').remove();
// Start adding Nodes to D3 Graphs
let entityNodes: D3.Selection < any > = nodeContainer
.attr('transform', 'translate(5,0)')
.attr('stroke-width', '3')
.attr('stroke', 'white')
.selectAll()
.data(sortedEntities)
.enter();
// Add new node
entityNodes
.append('g')
.attr('transform', function(d) {
return "translate(" + d.x + "," + d.y + ")"; // Set node position from packing algorithm
})
// Add event to each node
.on('mouseover',function (data) {
// If node is ever hovered on then call function to change the current active entity data and pass that D3 SVGs data to that function
this.changeActiveEntity(data); // This call doesn't work because 'this' has the SVG element as it's context not the Angular 2 component
} )
.on('mouseout', function(data) {
// D3 Svg is no longer "active" (Hovered) and so I want to update the active entity data to empty object
this.removeActiveEntity(); // This call doesn't work because 'this' has the SVG element as it's context not the Angular 2 component
})
.append('circle');
}
changeActiveEntity(newActiveEntity){
this.activeEntity = newActiveEntity;
}
removeActiveEntity(){
this.activeEntity = {};
}
}
You could use arrow functions to leverage the lexical this: 您可以使用箭头函数来利用词汇:
.on('mouseout', (data) => { // <----
// "this" corresponds now to the component instance
this.removeActiveEntity();
})
.on('mouseout', (data) => { // <----
// "this" corresponds now to the component instance
this.removeActiveEntity();
})
See this link for more details: 有关详细信息,请参阅此链接:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.