hpcc-systems/Visualization

Please surface click handlers in charts

clewisln opened this issue · 1 comments

There should be a way to assign custom event handlers to the charts. For example, when a user clicks a point in a scatter chart, the host application should be able to handle that click, without needing to extend the chart class.

Currently these bubble up to through the parent contexts. If the chart is added to a Chart Panel, then the event is essentially dropped:

//Scatter chart relay
.on("click", function (d: any, _idx) {
    context.click(host.rowToObj(host.data()[d.rowIdx]), d.column, host._selection.selected(this));
})

//Chart panel widget relay
tmpAny.click = function () {
    context.click.apply(context, arguments);
};

//Chart Panel event sink (deadend)
click(row, column, selected) {
    // console.log("Click:  " + JSON.stringify(row) + ", " + column + ", " + selected);
}

Instead, there should be a way of assigning a custom handler, through a published property assignment:

import { ChartPanel } from '@hpcc-js/layout';
export class CustomPanel extends ChartPanel {
  click() {
    const customHandler = this.onClick();
    typeof customHandler === "function" && customHandler.apply(this, arguments);
  }
}
CustomPanel.prototype.publish("onClick", null, "function", "Custom click handler");

Then:

const panel = new CustomPanel()
    .onClick((row, column, selected) => {
        ... custom handler logic here
    });

Note: this surfacing could also apply to other events, such as dblclick, vertex_click, vertex_dblclick, edge_click, edge_dblclick, etc.

If there is already an official way of doing this, without resorting to class extensions, please point me to the documentation.

The general pattern for event is normally:

const panel = new CustomPanel()
    .on("click", (row, column, selected) => {
        ... custom handler logic here
    });

And if you want to prevent propagation:

const panel = new CustomPanel()
    .on("click", (row, column, selected) => {
        ... custom handler logic here
    }, true);