lpcarignan
Posts: 36
Joined: Mon Mar 22, 2021 3:17 pm

React code in tooltip formatter

Hi,

My question is related to the tooltip formatter property and how I can call Javascript code from within the Html that I generate in this function.

I'm currently generating a tooltip in Html using the formatter function. This works fine for displaying static Html in the tooltip.

Silly example to illustrate my current state

Code: Select all

tooltip:formatter(){
    return <div>Some static code here</div>
}
I would like to go one step further in my toolitp by calling Javascript from the rest of my application. More precisely, I want to call a function that was defined by React.useState so I can add data to a series and show this series on the chart. In other words, imagine a Html button in the tooltip which calls a setOptions function which was initially defined like this:

Code: Select all

const [options, setOptions] = React.useState<Highcharts.Options>({ ... });
It is worth mentioning I'm using React with Typescript in a Single Page Application. So please keep this in mind if you believe you have an answer for me as my technology stack might have a few limitations.

I initially tried something similar to the tutorial How to display a chart in a toolip (https://www.highcharts.com/blog/tutoria ... e-tooltip/). This tutorial shows how to return code in the formatter function.

So I tried something similar by doing this

Code: Select all

            formatter: function () {
                return <MyFuncComponent></MyFuncComponent>
            }
This didn't work in a Typescript environment as I'm returning a JSX Element and the formatter function is expecting a string.

I investigated React.createPortal but couldn't get it to work inside the formatter function either.

My goal would be to do something similar to following code sample where I still have my static code AND I'm adding a button to call my Javascript code

Code: Select all

formatter: function () {
    return <div>Some static code here
        <button> click={() => setOptions({...})}></button>
    </div>
}

Would anyone have an idea on how I could do this?
kamil.k
Posts: 458
Joined: Thu Oct 06, 2022 12:49 pm

Re: React code in tooltip formatter

Hello lpcarignan,

Thanks for contacting us again!

There is a similar topic on our forum with the correct HTML element's event implementation inside the tooltip.formatter method, see: viewtopic.php?t=48311

Unfortunately, passing React components to this method is not supported for now. As you mentioned, using portals is probably the best workaround for that. Here is our official demo showing the implementation of portals: https://codesandbox.io/s/1o5y7r31k3.

Let me know if you will struggle to implement those features into your code,
Kind Regards!
Kamil Kubik
Highcharts Developer
lpcarignan
Posts: 36
Joined: Mon Mar 22, 2021 3:17 pm

Re: React code in tooltip formatter

Hi,

Thank you for your answer. I did look at the other topic but I find it's related to a pure Javascript environment. As I'm in a React/Typescript environment, I'm a bit more constrained than this.

I did have a look at your example about implementing portals.

I believe my context with a tooltip is different than in the demo shared in the previous post.

More precisely, I'm trying to do something similar to this:

Code: Select all

formatter: function(this: Highcharts.TooltipFormatterContextObject, tooltip: Highcharts.Tooltip) {
    let p = createPortal(<SomeReactComponent click={() => to something}></SomeReactComponent>, tooltip.container as HTMLElement);
    
    return p;
}
The formatter must return a string or an array of string based on the Highcharts Typed Definition file. So I can't just return the object p as shown above. I have to convert it to a string, which I don't believe I can do with createPortal.

The second argument of formattter is the actual tooltip object. Its container property should be set to some object when the outside property is set to true. In my code, the container property was always to undefined even if the property outside is set to true. My goal would be to use this container as the second parameter of the createPortal function.

Would you be able to assist me with my specific scenario?

Louis-Philippe
kamil.k
Posts: 458
Joined: Thu Oct 06, 2022 12:49 pm

Re: React code in tooltip formatter

Thanks for the clarification. Actually, using the portals in your case seems a little tricky. Based on your example you can easily set the tooltip.className property to refer to the DOM element. But my recommendation after debugging this is to use a different method to make it more optimized. Here is a great topic on our official React wrapper with possible solutions, take a look: https://github.com/highcharts/highchart ... /issues/23.

Based on this topic, there are two demos showing the correct ways to create a custom tooltip based on React components, see:
- https://codesandbox.io/s/highcharts-rea ... ked-9gmxiu
- https://codesandbox.io/s/highcharts-rea ... ked-vx0kqx

I hope you will find it useful in your case,
Regards!
Kamil Kubik
Highcharts Developer
lpcarignan
Posts: 36
Joined: Mon Mar 22, 2021 3:17 pm

Re: React code in tooltip formatter

Hi Kamil,

Thank you so much for your reply. The demos were very helpful to get me started and they solved my problem. I would have never resolved this by myself.

I googled a lot and never found the GitHub issue. I might be the only one doing React with functional components but for me, it was always weird to have the chart tooltip generated with pure Html in text while the rest of the app was in React. All of the examples I found around the tooltip formatter were in plain Html.

From now on, I'll be able to convert them to React functional components.

Maybe making more tutorials on this topic would help other React developers.

Louis
kamil.k
Posts: 458
Joined: Thu Oct 06, 2022 12:49 pm

Re: React code in tooltip formatter

That's great to hear you found it helpful!

There were such misleadings as that's not a handled feature by our current wrapper. I totally agree that it would be a great feature to implement and as more and more users struggle with that, it may happen in the future.

Feel free to ask any further questions,
Regards!
Kamil Kubik
Highcharts Developer
lpcarignan
Posts: 36
Joined: Mon Mar 22, 2021 3:17 pm

Re: React code in tooltip formatter

Hi Kamil,

I believe I've hit a limitation or a problem with how Highcharts tooltip works with a React.

I took your demo (https://codesandbox.io/s/highcharts-rea ... ooltip.tsx) as a starting point to solve my problem in my application.

I'm in a situation where my tooltip has a fixed width but the height depends on the content to display.

I tried all sorts of CSS tricks (overflow, height 100%, min height 100%) from StackOverflow questions to have the height of my tooltip change on each paint but none of them solved my issue.

In your code sample, I added a red background color to determine where this div is being drawn.

Code: Select all

<div style="background-color:#FF0000;width:420px" id="${generateTooltipId(chart.index)}"></div>
When I show a tooltip for the first time, I can see the red box of the outermost div like this:
FirstPaint.png
FirstPaint.png (58.77 KiB) Viewed 2198 times
There seems to be another div wrapping my red div (it's kind of beige in the picture). Highcharts seems to keep the height of this div.

I then move my mouse cursor to another point that has less info to show on the tooltip. The tooltip is kept the same height.
AfterFirstPaint.png
AfterFirstPaint.png (19.39 KiB) Viewed 2198 times
I can't figure out how to tell Highcharts the content has changed and it should re-evaluate the height of the tooltip. I understand that in your demo, the tooltip heights get bigger if, for example, we add more text in a div.

If I create the tooltip out of pure Html in the formatter function of the tooltip, without any React, the height always adjusts correctly based on the content of the tooltip.

But in this situation, where I create a portal inside the div, it doesn't do this anymore. I did read about React.createportal() and couldn't find any reason it was the guilty part of my problem.

As a workaround, for now, I've added a height attribute to the div like this

Code: Select all

<div style="background-color:#FF0000;width:420px; height:100px" id="${generateTooltipId(chart.index)}"></div>
A scrollbar appears so the user can at least scroll through the content.
Scrollbars.png
Scrollbars.png (37.52 KiB) Viewed 2198 times
But a more elegant solution would be to have a tooltip heights adapt to its content.

From a Highcharts tooltip perspective, is there something I forgot? I thought about creating a new DOM container element on each paint but it might get heavy on the DOM of the browser.

Louis-Philippe
lpcarignan
Posts: 36
Joined: Mon Mar 22, 2021 3:17 pm

Re: React code in tooltip formatter

Hi Kamil,

I've updated your demo to demonstrate my issue.

If you go to https://codesandbox.io/s/highcharts-rea ... /Chart.tsx, I've replaced the code generated in the Tooltip where I generate additional Html based on the current time.

On the first try, it can either generate a big tooltip with the <p> tag or a small one with the <b> tag. If it creates a big tooltip, move your cursor on the other points until it generates a small tooltip.

You will see the tooltip size is stuck to the first time it was generated.

I've taken a screenshot of the first time the tooltip is generated with a little bit of text in it.
FirstPaint.png
FirstPaint.png (19.21 KiB) Viewed 2179 times
Then, when I move my cursor around, when it hits the large tooltip, it keeps the size of the small tooltip
AllOtherSubsequentPaints.png
AllOtherSubsequentPaints.png (44.05 KiB) Viewed 2179 times
Does this help you out? How would you solve this?

Louis-Philippe
kamil.k
Posts: 458
Joined: Thu Oct 06, 2022 12:49 pm

Re: React code in tooltip formatter

Thanks for the clarification!

I think you should base on the context state of the tooltip and dynamically change its properties. I've updated the Tooltip file with a new useEffect hook, take a look: https://codesandbox.io/s/highcharts-rea ... ked-m76kgn.

Let me know if that works for you,
Regards!
Kamil Kubik
Highcharts Developer
lpcarignan
Posts: 36
Joined: Mon Mar 22, 2021 3:17 pm

Re: React code in tooltip formatter

Hi Kamil,

The addition of useEffect on the context worked. My tooltip now resizes correctly.

One last question. Do you know if the createPortal technique discussed here would work on other formatters like the axis formatter?

Thank you so much for your guidance.

Louis-Philippe
kamil.k
Posts: 458
Joined: Thu Oct 06, 2022 12:49 pm

Re: React code in tooltip formatter

You're welcome, I'm glad I could help you with that!

Yes, this solution should be working with other formatter methods as well. If you will face any issues implementing it, freely let me know.

Regards!
Kamil Kubik
Highcharts Developer
vsanse
Posts: 6
Joined: Wed Dec 28, 2022 8:17 am

Re: React code in tooltip formatter

Hi Kamil,
Looks like the solution mentioned in the thread breaks if we have enabled the shared tooltip. Please refer the codesanbox link below.
https://codesandbox.io/s/highcharts-rea ... /Chart.tsx
vsanse
Posts: 6
Joined: Wed Dec 28, 2022 8:17 am

Re: React code in tooltip formatter

Update:
I fixed/updated the code to work with shared tooltip but there is a problem where stickOnContact doesn't work with outside true property
reference: https://codesandbox.io/s/highcharts-rea ... /Chart.tsx
kamil.k
Posts: 458
Joined: Thu Oct 06, 2022 12:49 pm

Re: React code in tooltip formatter

Hello There!

You were right about the slightly changed point data reference once the tooltip.shared property is enabled.
Please, refer to this example: https://codesandbox.io/s/highcharts-rea ... ked-3mxnsg. I refactored the way of refreshing the tooltip, adding some safety checks.

Let me how if it works for you,
Regards!
Kamil Kubik
Highcharts Developer
vsanse
Posts: 6
Joined: Wed Dec 28, 2022 8:17 am

Re: React code in tooltip formatter

Great. Thanks for the updated demo. But there is another issue that I encountered. When points are too close to each other and the tooltip content is large, it covers the point and leads to bad UX.
https://i.imgur.com/eUqi8me.png

Return to “Highcharts Usage”