我的问题:我在 Angular 2 组件中使用 D3 在屏幕上绘制 SVG。这工作正常,但我想将事件附加到 D3 生成的 SVG,并在该事件中调用我的 Angular 2 组件中的方法。该方法将采用 D3 SVG 提供的数据并将其分配给 Angular 2 父组件中的一个变量。该变量是我的 Child Angular 2 组件的输入变量。我目前无法从 D3 事件回调中调用 Angular 2 组件中的函数。关键字“this”在回调中的上下文与在 Angular 2 组件中使用它时的上下文不同,因此我无法获得能够调用我想要的函数的引用。
我的项目:所以我有一个 Angular 2 项目,我有 2 个具有父子关系的组件。 D3 Canvas 组件是父组件,正如您在下面看到的,我在该组件模板中包含一个数据详细信息面板。 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>
现在在初始化 D3 图形并可视化数据的 Angular 2 组件中,这是它的设置方式:
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 = {};
}
}
最佳答案
您可以使用箭头函数来利用词法 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();
})
有关详细信息,请参阅此链接:
关于javascript - Angular 2 D3 事件、变更检测和上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38868996/