How to Use Chart.js in Retool Using a Custom Component
Retool provides a versatile platform for quickly building internal tools, and extending its functionality with custom components is one of its strengths. In this article, we'll guide you through integrating Chart.js into Retool using a custom React component. We'll use sample data representing players’ ages to demonstrate the process. Follow these steps to visualize your data in a pie chart using Chart.js.
Sample Data:
We’ll use the following data to create our pie chart. This data will be included in the model of the custom component:
{ "data": {
"x": ["Below 14", "14-16", "16-18", "18-20", "20-22", "22-24", "Above 24"],
"y": [29.79, 4.26, 0, 4.26, 34.04, 4.26, 23.4]
}}
HTML Structure:
Start by setting up the basic HTML and CSS structure within your Retool custom component:
<style>
.component {
border: 1px solid #CDA6DF;
width: 100%;
height: 100%;
border-radius: 12px;
background-color: #FFFFFF;
padding: 10px;
box-sizing: border-box;
}
.main {
background-color: #F2ECF5;
padding: 10px;
margin-top: 10px;
border-radius: 12px;
}
.root, .unique {
display: flex;
justify-content: space-between;
margin-bottom: 10px;
}
.first, .second {
border-bottom: 1px solid #CDA6DF;
color: #000000;
width: 100%;
font-family: 'Poppins', sans-serif;
font-size: 14px;
font-weight: 400;
line-height: 18px;
text-align: center;
}
.line {
height: 30px;
}
.percentage {
font-family: 'Poppins', sans-serif;
font-size: 24px;
font-weight: 400;
line-height: 31px;
text-align: center;
}
#myChart {
margin: 0 auto;
height: 380px !important;
width: 380px !important;
}
.title {
font-family: 'Poppins', sans-serif;
font-size: 18px;
font-weight: 400;
line-height: 23px;
color: #7C3C9B;
text-align: center;
}
.no-data {
text-align: center;
color: #BFBFBF;
font-family: 'Poppins', sans-serif;
font-size: 18px;
font-weight: 400;
line-height: 23px;
height: 325px;
display: flex;
justify-content: center;
align-items: center;
}
</style>
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<div id="react"></div>
Creating the React Component:
Next, we’ll create a React component that renders the Chart.js pie chart using the sample data. Add the following script to your custom component:
<script type="text/babel">
const { useEffect, useRef } = React;
const MyCustomComponent = ({ model }) => {
const colors = [
'#FD6AF8',
'#41B54A',
'#F7971C',
'#2D67B1',
'#555555',
'#EC1F24',
'#C561F7'
];
const chartRef = useRef(null); // Ref to store chart instance
const prevDataRef = useRef([]); // Ref to store previous data
// Helper function to check if all values in an array are null
function allValuesAreNull(arr) {
return arr.every(value => value === null);
}
useEffect(() => {
const ctx = document.getElementById("myChart").getContext("2d");
// Function to destroy the chart
const destroyChart = () => {
if (chartRef.current) {
chartRef.current.destroy();
chartRef.current = null;
}
};
// Function to create or update the chart
const createOrUpdateChart = () => {
if (!chartRef.current) {
chartRef.current = new Chart(ctx, {
type: 'pie',
data: {
labels: model.data.x,
datasets: [{
label: 'Ages in %',
data: model.data.y,
backgroundColor: colors,
borderColor: "#FFFFFF",
borderWidth: 1.5,
}]
}
});
} else {
chartRef.current.data.labels = model.data.x;
chartRef.current.data.datasets[0].data = model.data.y;
chartRef.current.update();
}
prevDataRef.current = model.data.y;
};
// Create chart if there's data
if (!allValuesAreNull(model.data.y)) {
createOrUpdateChart();
} else {
destroyChart();
}
// Cleanup on component unmount
return destroyChart;
}, [model.data, colors]);
if (allValuesAreNull(model.data.y)) {
return (
<div className="component">
<span className="title">Ages of players</span>
<div className="no-data">No Data Found</div>
</div>
);
}
return (
<div className="component">
<span className="title">Ages of players</span>
<canvas id="myChart" width="400" height="400"></canvas>
<div className="main">
{model.data.x.map((age, index) => (
<div className={index === 6 ? "unique" : "root"} key={index}>
<div className="first">
Age {index === 0 || index === 6 ? age : `between ${age}`}
<span className="percentage" style={{ color: colors[index] }}>
{model.data.y[index]}%
</span>
</div>
{index % 2 !== 0 && <div className="line"></div>}
</div>
))}
</div>
</div>
);
};
const ConnectedComponent = Retool.connectReactComponent(MyCustomComponent);
const container = document.getElementById("react");
const root = ReactDOM.createRoot(container);
root.render(<ConnectedComponent />);
</script>
Explanation:
HTML and CSS Structure: Define the basic styles and structure of the component to ensure it fits well within the Retool dashboard.
React Component Setup: Use React’s useEffect hook to manage the lifecycle of the Chart.js instance, creating or updating the chart based on the provided model data.
Helper Functions:
allValuesAreNull
: Checks if all values in the data array are null.
Chart Management:
createOrUpdateChart
: Either create a new chart or update the data in the existing chart.destroyChart
: Destroys the chart if there is no valid data or when the component unmounts.
Data Handling: Checks if there’s data to display; if not, it renders a “No Data Found” message.
Component Mounting: Use Retool’s
Retool.connectReactComponent
to connect the custom React component with the Retool framework.
Conclusion:
By following these steps, you can successfully integrate Chart.js within a Retool custom component to visualize data with interactive pie charts. This approach offers flexibility, allowing you to further customize the chart according to your application’s needs.
Experiment with different chart types and data sets to unlock the full potential of custom components in Retool, enhancing your internal tools and dashboards.