Part 1 of 3: Controlling Plotly in React – Control the Modebar
How to take control of Plotly’s modebar buttons with a single, straightforward React hook.
Are you gearing up to write a new data app?
Does your business contain critically huge amounts of data that are interpreted best when visualized?
Do you want to make your data points interactive for the user without writing a ton of code?
Consider using plotly.
Plotly?
Ploty is a popular, feature-rich solution for writing data visualization apps with relatively small amounts of code. Scatter plot charts, bar charts, 3D charts, maps, and much more are all possible with plotly.
In this article…
I’ll be showing you how to control plotly’s modebar buttons with a simple React hook. We’ll control them by selecting their base anchor elements in the HTML, then creating buttons that trigger a click for those elements
You should already have a basic understanding of:
- Javascript
- Typescript (this app will be in Typescript!)
- Plotly in react
- React and React hooks
Steps in creating this hook to control plotly’s modebar:
- Create the app in codesandbox.io
- Import dependencies and starting code
- Create new file for hook
- Extract types
- Write the hook logic
- Use hook in main app
- Hide existing plotly modebar
Create the app in codesandbox.io
Begin by going to codesandbox.io. Click on the “Create” button at the top, then select “React Typescript”
Import dependencies and starting code:
In the “Dependencies” section on the left, import the following dependencies:
- @types/react-plotly.js
- Plotly.js
- React-plotly.js
Your dependency list should look like this (the other dependencies should already be installed):
import Plot from "react-plotly.js";
import "./styles.css";
const count = 50;
const getArray = () => Array(count).fill(1);
const getRandomNumber = (max: number) => Math.floor(Math.random() * max);
const startingNumbers = getArray().map((_, i) => i);
const randomNumbers = getArray().map(() => getRandomNumber(count));
export default function App() {
return (
<div className="App">
<Plot
data={[
{
x: startingNumbers,
y: randomNumbers,
mode: "markers"
}
]}
layout={{
title: "Plotly App",
xaxis: { range: [-5, count] },
yaxis: { range: [-5, count] },
dragmode: "lasso",
uirevision: 1
}}
/>
</div>
);
}
Create new file for hook
Right click on the “src” directory on the left and click on Create File. Call the file “usePlotlyModebar.ts”
Extract types
At the top of the usePlotlyModebar.ts file, paste the following code
// these strings are the datatitles for plotly's modebar <a> elements
export const modebarActions = [
"Pan",
"Box Select",
"Lasso Select",
"Download plot as a png",
"Autoscale",
"Zoom out",
"Zoom in"
] as const;
type ModebarAction = typeof modebarActions[number];
Wait! Where did these strings (“Pan”, “Box Select”, etc…) come from?
If you inspect the modebar element and expand down to the bottommost elements, you’ll see that the modebar buttons are anchor elements with unique data-titles. These strings are the data-titles for these anchor elements and we will use them to select these anchor elements and eventually click them.
Wait (again)! Why make a const and a type and not just a type?
You’ll notice I first make an array of strings (const modeBarActions) and then I make a type based on the strings in the array (type ModebarAction). So why didn’t I just make the type? It’s because I plan on iterating over each action string and you can’t do that with a type.
Write the hook logic
Underneath the code written in the previous step, write this hook:
export const usePlotlyModebar = () => {
const triggerModebarButton = (action: ModebarAction) => {
const anchorElement = document.querySelector<HTMLAnchorElement>(
`[data-title="${action}"]`
);
anchorElement?.click();
};
return { triggerModebarButton };
};
Explanation of code:
The hook contains a single method (triggerModebarButton) that receives a ModebarAction string. That string is used to select the unique modebar button based on the anchor’s data-title, which we then click.
Use hook in main app
In App.tsx, in the App component, import modebarActions and usePlotlyModebar then add the usePlotlyModebar hook in the first line of the component.
Next, in the return JSX before the plot, add the code that will return a button for each modebarAction:
import { modebarActions, usePlotlyModebar } from "./usePlotlyModebar";
// other code…
export default function App() {
const { triggerModebarButton } = usePlotlyModebar();
return (
<div className="App">
{modebarActions.map((action) => (
<button
style={{ marginRight: "2px" }}
onClick={() => triggerModebarButton(action)}
>
{action}
</button>
))}
{/* other code… */}
Hide existing plotly modebar
Finally, go to styles.css and add the following code. It will hide the existing plotly modebar so you won’t see both. And that’s it!
.modebar-container * {
visibility: hidden;
}
Conclusion
Here’s a link to a finished codesandbox: https://codesandbox.io/s/plotly-modebar-buttons-exc9qh?file=/src/App.tsx
In the next article for this 3 part series on Controlling plotly in React, I’ll be showing you how to render fully custom annotations.
Parts
Part 1 of 3: Controlling Plotly in React – Control the Modebar
Part 2 of 3: Controlling Plotly in React – Fully Custom Annotations
Part 3 of 3: Controlling Plotly in React – Adding Custom Color Markers by Category
About Black Slate
Black Slate is a Software Development Consulting Firm that provides single and multiple turnkey software development teams, available on your schedule and configured to achieve success as defined by your requirements independently or in co-development with your team. Black Slate teams combine proven full-stack, DevOps, Agile-experienced lead consultants with Delivery Management, User Experience, Software Development, and QA experts in Business Process Automation (BPA), Microservices, Client- and Server-Side Web Frameworks of multiple technologies, Custom Portal and Dashboard development, Cloud Integration and Migration (Azure and AWS), and so much more. Each Black Slate employee leads with the soft skills necessary to explain complex concepts to stakeholders and team members alike and makes your business more efficient, your data more valuable, and your team better. In addition, Black Slate is a trusted partner of more than 4000 satisfied customers and has a 99.70% “would recommend” rating.