javascript - Angular 2 D3 Event, Change Detection and Context - Stack Overflow

My Issue: I am using D3 in an Angular 2 ponent to draw SVGs on the screen. This works fine, however I w

My Issue: I am using D3 in an Angular 2 ponent to draw SVGs on the screen. 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. That method will take the Data provided by the D3 SVG and assign it to a variable in my Angular 2 Parent ponent. That variable is an Input variable for my Child Angular 2 ponent. I cannot currently call the Function in the Angular 2 Component from within the D3 event callback. The keyword "this" has a different context from within the callback than when using it within an Angular 2 ponent and thus I cannot get a reference to be able to call the function I want.

My Project: So I have an Angular 2 Project and I have 2 Components with a Parent - Child Relationship. The D3 Canvas Component is the Parent and as you can see below I have a data-detail-panel contained within this ponent template. data-detail-ponent is powered by the Input Variable 'activeEntity' which I want to be populated based upon the D3 event when the SVG is hovered on.

<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:

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 ponent 
      } )
      .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 ponent
      })
      .append('circle');

  }
  changeActiveEntity(newActiveEntity){
    this.activeEntity = newActiveEntity;
  }
  removeActiveEntity(){
    this.activeEntity = {};
  }
}

My Issue: I am using D3 in an Angular 2 ponent to draw SVGs on the screen. 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. That method will take the Data provided by the D3 SVG and assign it to a variable in my Angular 2 Parent ponent. That variable is an Input variable for my Child Angular 2 ponent. I cannot currently call the Function in the Angular 2 Component from within the D3 event callback. The keyword "this" has a different context from within the callback than when using it within an Angular 2 ponent and thus I cannot get a reference to be able to call the function I want.

My Project: So I have an Angular 2 Project and I have 2 Components with a Parent - Child Relationship. The D3 Canvas Component is the Parent and as you can see below I have a data-detail-panel contained within this ponent template. data-detail-ponent is powered by the Input Variable 'activeEntity' which I want to be populated based upon the D3 event when the SVG is hovered on.

<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:

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 ponent 
      } )
      .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 ponent
      })
      .append('circle');

  }
  changeActiveEntity(newActiveEntity){
    this.activeEntity = newActiveEntity;
  }
  removeActiveEntity(){
    this.activeEntity = {};
  }
}
Share Improve this question asked Aug 10, 2016 at 9:13 RiceheadRicehead 551 silver badge6 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 8

You could use arrow functions to leverage the lexical this:

.on('mouseout', (data) => { // <----
  // "this" corresponds now to the ponent instance
  this.removeActiveEntity();
})
.on('mouseout', (data) => { // <----
  // "this" corresponds now to the ponent instance
    this.removeActiveEntity();
})

See this link for more details:

  • https://developer.mozilla/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions#Lexical_this

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745004773a4605711.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信