I have added apexcharts in my next app. The chart is working fine. But the problem is I want to add custom toolbar like sidebar with charts. So I added the UI for it. But now I want to make the icons functional. They are actually showing in toolbar in side.
this is the code:
interface IState {
series: Array<{
data: Array<{
x: Date,
y: number[]
}>
}>,
options: {
chart: {
type: string,
toolbar: {
show: boolean,
},
},
xaxis: {
type: string,
show: boolean,
labels: {
show: boolean,
style: {
colors: string,
},
},
axisBorder: {
show: boolean,
},
axisTicks: {
show: boolean,
},
},
yaxis: {
opposite: boolean,
show: boolean,
labels: {
show: boolean,
style: {
colors: string,
},
},
axisBorder: {
show: boolean,
},
axisTicks: {
show: boolean,
},
},
grid: {
show: boolean,
borderColor: string,
strokeDashArray: number,
xaxis: {
lines: {
show: boolean,
color: string,
},
},
yaxis: {
axisBorder: {
show: boolean,
},
lines: {
show: boolean,
},
},
},
plotOptions: {
candlestick: {
colors: {
upward: string,
downward: string,
},
},
},
},
}
const BodyChart: React.FC = () => {
const chartRef = useRef<ReactApexChart | any>(ReactApexChart);
const [state] = React.useState<IState>({
series: [{
data: [
// my data
]
}],
options: {
chart: {
type: 'candlestick',
toolbar: {
show: false, // Hide the default toolbar
},
},
xaxis: {
type: 'datetime',
show: true,
labels: {
show: true,
style: {
colors: '#969AA4',
},
},
axisBorder: {
show: false,
},
axisTicks: {
show: false,
},
},
yaxis: {
opposite: true,
show: true,
labels: {
show: true,
style: {
colors: '#969AA4',
},
},
axisBorder: {
show: false,
},
axisTicks: {
show: false,
},
},
grid: {
show: true,
borderColor: '#202530',
strokeDashArray: 0,
xaxis: {
lines: {
show: true,
color: '#FF5733',
},
},
yaxis: {
axisBorder: {
show: false,
},
lines: {
show: true,
},
},
},
plotOptions: {
candlestick: {
colors: {
upward: '#009B84',
downward: '#FF1230',
},
},
},
},
});
useEffect(() => {
const chart = chartRef.current.charts;
document.getElementById('zoom-in')?.addEventListener('click', () => {
// chart.zoomIn();
});
document.getElementById('zoom-out')?.addEventListener('click', () => {
chart.zoomOut();
});
document.getElementById('reset')?.addEventListener('click', () => {
chart.reset();
});
}, []);
return (
<div className="container">
<div className="sidebar">
<button id="zoom-in"><FontAwesomeIcon icon={faSearchPlus} color='#969AA4' /></button>
<button id="zoom-out"><FontAwesomeIcon icon={faSearchMinus} color='#969AA4' /></button>
<button id="reset"><FontAwesomeIcon icon={faUndo} color='#969AA4' /></button>
<button id="home"><FontAwesomeIcon icon={faHome} color='#969AA4' /></button>
<button id="menu"><FontAwesomeIcon icon={faBars} color='#969AA4' /></button>
<button id="download"><FontAwesomeIcon icon={faDownload} color='#969AA4' /></button>
<button id="selection"><FontAwesomeIcon icon={faMousePointer} color='#969AA4' /></button>
<button id="zoom"><FontAwesomeIcon icon={faSearch} color='#969AA4' /></button>
<button id="pan"><FontAwesomeIcon icon={faArrows} color='#969AA4' /></button>
</div>
<div className="chart-wrapper">
<div id="chart">
<ReactApexChart ref={chartRef} options={state.options} series={state.series} type="candlestick" height={535} />
</div>
<div id="html-dist"></div>
</div>
</div>
);
}
note: I have tried using chartRef but it did not worked
The useRef
hook might be the issue here. From the docs #caveats,
When you change the ref.current property, React does not re-render your component. React is not aware of when you change it because a ref is a plain JavaScript object.
The chart
should be created by defining a unique ID, and later methods can be invoked in useEffect
or button events (from react-apexcharts).
Apex Charts provides zoomX(start, end)
method, where start
and end
can be x-axis value, or timestamp.
To reset the zoom resetSeries(updateChart, resetZoom)
method can be used.
For instance to zoom-in the chart by 5-minute window around current time:
...
const [state] = React.useState<IState>({
series: [{
data: [
// my data
]
}],
options: {
chart: {
id: 'myChart' // <=== THIS
type: 'candlestick',
toolbar: {
show: false, // Hide the default toolbar
},
},
...
const _getZoomInDuration = () => {
now = new Date();
startTimestamp = new Date(new Date(now.getTime() - minutes*60000));
endTimestamp = new Date(new Date(now.getTime() + minutes*60000));
return { start:startTimestamp, end:endTimestamp }
}
useEffect(() => {
duration = _getZoomInDuration();
const chart = ApexCharts.getChartByID('myChart') // <== THIS
document.getElementById('zoom-in')?.addEventListener('click', () => {
chart.zoomIn(duration.start, duration.end);
});
document.getElementById('zoom-out')?.addEventListener('click', () => {
chart.zoomIn(<larger.start>, <larger.end>);
});
document.getElementById('reset')?.addEventListener('click', () => {
chart.resetSeries(true, true);
});
}, []);
return (
...
<div className="chart-wrapper">
<div id="chart">
<ReactApexChart options={state.options} series={state.series} type="candlestick" height={535} />
</div>
<div id="html-dist"></div>
</div>
)
Also, callbacks can be attached to react to chart events.