How to add event handler in grafana 8 react panel plugins

I’m developing custom panel plugin for grafana 8.3.3. I need to handle event after panel html has loaded, but I don’t know how can I register event in new version of grafana plugins. I found This PanelEvents docs but I don’t know how can I use panel events. Could anyone provide me some example for doing this?
Thanks in advance

1 Like

Could you share more about what you’d like to do when the panel has loaded? What events are you interested in?

1 Like

Thank you for your response. I want to use jquery jstree plugin in my grafana panel plugin. I need to first generate tree struture in nested <ul><li>...</li></ul> formats and after rendering html, I need to call $("#tree").jstree(). But I don’t know where can I call this function. Here is the example of my plugin code:

interface Props extends PanelProps<SimpleOptions> {}

export const SimplePanel: React.FC<Props> = ({ options, data, width, height }) => {
  
  return (

    <div >
      <div id="tree">
        <ul>
          <li>Root node 1</li>
          <li>Root node 2</li>
        </ul>
      </div>
      // I tried calling $("#tree").jstree() inside {} here but, but it seems the <div id="tree"> is undefined here
    </div>
  );
};

I’ve developed this plugin in older version of grafana(6) without any problem. But I don’t know How can I do this in this version. I know, maybe my approach is incorrect in this version, But I need to use jquery and I need to call jquery functions after complete rendering of html.

In older versions before 7, I could bind event to my panel in this way:

    this.events.on('render', this.onRender.bind(this));
    this.events.on('data-received', this.onDataReceived.bind(this));
    this.events.on('data-error', this.onDataError.bind(this));
    this.events.on('data-snapshot-load', this.onDataReceived.bind(this));
    this.events.on('init-edit-mode', this.onInitEditMode.bind(this));
    ...
1 Like

Hi,

I also would like to chime in here in order to signal strong interest on this topic.

We conceived the GitHub - panodata/grafanimate: Animate timeseries data with Grafana program the other day and just recently gave it some love, aiming to make it ready with recent versions of Grafana. However, we also discovered that the venerable data-received-type events were gone with the new internal architecture based on React. We also tried to fiddle a bit with the new PanelEvents | Grafana Labs, to no avail.

In general, we are wondering if using corresponding panel events with React would now need any kind of software component to link with the Grafana SDK/Toolkit in order to be able to use corresponding symbols?

I am asking this maybe naive question because, beforehand, it was easy to inject arbitrary Javascript code (grafana-studio.js) into the window’s scope in order to get hold of the active dashboard object [1]. On this object, we were able to install the same event handlers as outlined above by @hamed, using named events identified by plain text labels.

In order to get a synchronized signal after all panels successfully received their data, we made grafana-studio.js::onDashboardRefresh capture the data-received, data-frames-received, data-error and dashboard-fetch-end events from all panels and synthesize an all-data-received event from it.

With this machinery in place, grafanimate was able to efficiently produce animations. Currently, we are working around it by having introduced a mechanism to Add parameter "--exposure-time", defaulting to 0.5 seconds · panodata/grafanimate@1f183d1 · GitHub, which the user would have to adjust appropriately. This definitively involves quite an amount of trial and error in order to get the right “exposure time” in different scenarios, as it very much depends on the number of panels and response times from the underlying databases.

As we didn’t follow the evolution of the Grafana code base into React land closely, and we might lack some essential React skills to get an idea about how to use the new PanelEvents, maybe you can share some resources where we would be able learn more about them?

Thank you already and with kind regards,
Andreas.


  1. angular.element("grafana-app").injector().get("dashboardSrv").getCurrent() ↩︎

It looks like you could use the useEffect and useRef hook to get a reference to the HTML element.

Haven’t tested it, but you should be able to do something like this:

const treeContainer = useRef(null);
useEffect(
  () => {
    if (treeContainer.current) {
      treeContainer.current.jstree();
    }
  },
  [treeContainer.current])

Maybe this article on Simple D3 with React Hooks can give you some inspiration.

That’s a cool looking tool! :hushed:

I haven’t had a chance to play around with it yet, but the React platform has an event bus that you could look into. It’s available from the panel props, props.eventBus, in recent versions of Grafana.

For an example on how to subscribe to events, you can check out the pie chart panel:

1 Like

Dear Marcus,

thank you for sharing this pointer. Apologies for hijacking this discussion, @hamed. I hope this helps you as well. Otherwise, feel free to move our discussion into another thread, @marcusolsson.

Introduction

I already tried to play around a bit with the React event bus, but most probably did it wrong by poking around without knowing anything.

I will definitively look into this on the next iteration. In order to prepare myself as good as possible, I am humbly adding some additional questions on this matter.

Subscribing to events

Do you have any insights if it would be possible to resolve events (eventBus.getStream(DataHoverEvent)) by plain strings instead of typed symbols?

According to the definition of DataHoverEvent,

it would be sweet if, for example, eventBus.getStream("data-hover") actually worked [1]. If that would not work, I guess I would need another way to get hold of a reference to the corresponding event class from the grafana-data package. Please educate me on this matter: I believe there is no way to import or require arbitrary symbols from plain Javascript at runtime, right?

Figuring out the right events

For most of its current business, grafanimate is interested in events around the initialization and data-loading phases and lifecycles.

Looking at grafana/packages/grafana-data/src/events at main · grafana/grafana · GitHub, I remember not having been able to quickly figure out the appropriate event names. Combined with grafanimate’s needs to subscribe to events identified by plain string symbols as outlined above, I quickly lost track – probably also because it already was late at night.

Do you know if the React event bus also accepts wildcard subscriptions? That would enable users naively poking around like me to explore the possible event types (and their sequence flow) interactively. Otherwise, I will also be curious to discover a complete list of events you might be maintaining elsewhere because I well might have missed it due to lack of time to research this topic thoroughly enough.

Connecting the dots

I am reading a bit through those patches submitted by @torkel, thank you.

Coming from there, after further searching the code base, I believe that those legacy PanelEvents is what I would like to unlock again.

Thanks again for listening to my needs.

With kind regards,
Andreas.


  1. I know grafanimate takes an unorthodox approach by injecting its grafana-studio.js as plain Javascript into the page instead of shipping a corresponding plugin which the user would install into Grafana. However, this makes it operate on any Grafana instance without further ado. ↩︎

I just published a small guide for subscribing to application events:

Let me know if there’s anything I missed!

2 Likes

Thank you very much, Marcus! I will try to apply the corresponding insights to the next iteration of grafanimate. I am sure others from the community will also find this resource very valuable.

1 Like