How to define a custom tooltip in Apex chart in React? - reactjs

I am defining four lines chart with Apex Chart.
My data series:
series: [
{
name: "first",
data: [28, 29, 33, 36, 32, 32, 33]
},
{
name: "second",
data: [12, 11, 14, 18, 17, 13, 13]
},
{
name: "third",
data: [48, 29, 33, 16, 32, 62, 3]
},
{
name: "forth",
data: [22, 11, 54, 18, 27, 53, 13]
}
],
I want my tooltip output to be like:
first-label : {series.dataOfFirstLabel}
second-label : {series.dataOfSecondLabel}
third-label : {series.dataOfThirdLabel}
forth-label : {series.dataOfForthLabel}
How can I define my custom tooltip?
Thanks.

Try this:
tooltip: {
custom: function (series: any) {
return `<div>
${series.map((el: any) => {
return `<div class="d-flex flex- column">
<p>${el.name}-label:${el.data.map((element: any)=>element).join("")}</p> </div>`; })
</div>`},}
https://codepen.io/apexcharts/pen/NBdyvV

In chart options
enter code here
tooltip: {
enabled: true,
enabledOnSeries: true,
shared: true,
followCursor: true,
intersect: false,
inverseOrder: false,
custom: undefined,
fillSeriesColor: true,
theme: false,
style: {
fontSize: "12px",
fontFamily: undefined,
},
onDatasetHover: {
highlightDataSeries: false,
},
x: {
show: true,
format: "dd MMM",
formatter: undefined,
},
y: {
show: false,
formatter: undefined,
title: {
formatter: (seriesName) => seriesName,
},
},
z: {
formatter: undefined,
title: "Size: ",
},
marker: {
show: false,
},
items: {
display: "flex",
},
fixed: {
enabled: false,
position: "topRight",
offsetX: 0,
offsetY: 0,
},
},
//sh
you can add these properties
refer - https://apexcharts.com/docs/options/tooltip/

Instead string literal you can use renderToString from react-dom/server.
import { renderToString } from 'react-dom/server'
So the custom function would look like this:
// Some series that you use in the chart
const seriesData = [
{
name: 'South',
data: [
[1486771200000, 40],
[1486857600000, 18],
[1486944000000, 43],
],
},
{
name: 'North',
data: [
[1486771200000, 16],
[1486857600000, 15],
[1486944000000, 10],
],
}]
...
// Tooltip option for apexChart
tooltip: {
custom: ({ series, seriesIndex, dataPointIndex, w }) => {
const xValue = seriesData[seriesIndex].data[dataPointIndex][0]
const xDate = new Date(xValue).toLocaleDateString('cs-CZ')
return renderToString(
<div>
<p>
{xDate}
</p>
{/* Map through series to get labels and values */}
{seriesData.map((s, i) => (
<div key={s.name} className="tooltipItem">
<div style={{
minWidth: "12px",
backgroundColor: w.globals.colors[i]
}}
/>
<p >
MyLabel:{' '}
</p>
<p>
{series[i][dataPointIndex]}
</p>
</div>
))}
</div>
)
},
},

Related

How can I add padding bottom after the x-axis label using apexchart

I am having this Apex chart in my react app ,
What I want to do is add more space between the x-axis label which is the month labels and the series name below it (Session Duration, Page Views, Total Visits). How can I achieve that
This is my code below
............................................................................................................................
class ApexChart extends React.Component {
constructor(props) {
super(props);
this.state = {
series: [{
name: "Session Duration",
data: [45, 52, 38, 24, 33, 26, 21, 20, 6, 8, 15, 10]
},
{
name: "Page Views",
data: [35, 41, 62, 42, 13, 18, 29, 37, 36, 51, 32, 35]
},
{
name: 'Total Visits',
data: [87, 57, 74, 99, 75, 38, 62, 47, 82, 56, 45, 47]
}
],
options: {
chart: {
height: 350,
type: 'line',
zoom: {
enabled: false
},
},
dataLabels: {
enabled: false
},
stroke: {
width: [5, 7, 5],
curve: 'straight',
dashArray: [0, 8, 5]
},
title: {
text: 'Page Statistics',
align: 'left'
},
legend: {
tooltipHoverFormatter: function(val, opts) {
return val + ' - ' + opts.w.globals.series[opts.seriesIndex][opts.dataPointIndex] + ''
}
},
markers: {
size: 0,
hover: {
sizeOffset: 6
}
},
xaxis: {
categories: ['01 Jan', '02 Jan', '03 Jan', '04 Jan', '05 Jan', '06 Jan', '07 Jan', '08 Jan', '09 Jan',
'10 Jan', '11 Jan', '12 Jan'
],
},
tooltip: {
y: [
{
title: {
formatter: function (val) {
return val + " (mins)"
}
}
},
{
title: {
formatter: function (val) {
return val + " per session"
}
}
},
{
title: {
formatter: function (val) {
return val;
}
}
}
]
},
grid: {
borderColor: '#f1f1f1',
}
},
};
}
render() {
return (
<div id="chart">
<ReactApexChart options={this.state.options} series={this.state.series} type="line" height={350} />
</div>
);
}
}
Based on some fiddling around with the Appchart demo, found 2 options that seem to provide result here.
Both use the legend key inside options, which you have in your code
You can add specific height to the legend container
legend: {
height: 100
}
This will allow you to add margin to each legend.
legend: {
itemMargin: {
horizontal: 20
}
}
Hopefully someone with more experience with AppChart can provide a better solution but till then you can look into these.

set different bar width for each bar using ECHARTS

Im using the e-charts libary for creating a bar chart for my data .
like so :
option.series = [
{
name: 'buy',
type: 'bar',
stack: 'one',
data: Object.values(chartData?.data || {}).map(elem => -elem.buy?.total),
color: colors.bought,
label: {
show: true,
position: "bottom",
formatter: (value) => Math.round(Math.abs(value.data))
},
tooltip: {
formatter: (data) => Math.abs(data.value).toString()
},
// barWidth:this.data
},
{
name: 'sell',
type: 'bar',
stack: 'one',
data: Object.values(chartData?.data || {}).map(elem =>elem.sell?.total),
color: colors.sold,
label: {
show: true,
position: "top",
formatter: (value) => Math.round(Math.abs(value.data))
},
tooltip: {
formatter: (data) => Math.abs(data.value).toString()
},
},
{
name: 'profite',
type: 'bar',
stack: 'two',
barGap: '-100%',
z: 100,
data: Object.values(chartData?.data || {}).map(elem => elem.sell?.profit),
color: colors.profit,
label: {
show: true,
position: "insideTop",
textBorderWidth: -1,
offset: [0, -20],
formatter: (value) => Math.round(Math.abs(value.data))
},
tooltip: {
formatter: (data) => Math.abs(data.value).toString()
},
},
]
im trying to set a different width for each bar depending on the value of each bar .
on data property i get a list of numbers rendering .
When i try to add a barWidth property all i can do is change all of the bars in the same chrts like so for example:
barWidth: ${getBarWidth((Object.values(chartData?.data || {}).map((elem) => elem.sell?.amount)))}%
so i returne a different value of my data each time but it didnt changed each bar according to its value (either buy, sell and so on).
Thanks in adavance.
As you pointed out, barWidth sets the width of all the bars of a bar series. And I don't think there is a way to set the width of each bar in the same bar series.
What you should use instead is a custom series.
Custom series have a parameter called renderItem, where you write the render logic of the chart. It's where you'll be able to display custom shapes (custom sized bar in your case), using graphics.
Here is an example I found on their website, doing pretty much what you're looking for.
var container = document.getElementById('main');
var chart = echarts.init(container);
const colorList = [
'#4f81bd',
'#c0504d',
'#9bbb59',
'#604a7b',
'#948a54',
'#e46c0b'
];
const data = [
[10, 16, 3, 'A'],
[16, 18, 15, 'B'],
[18, 26, 12, 'C'],
[26, 32, 22, 'D'],
[32, 56, 7, 'E'],
[56, 62, 17, 'F']
].map(function (item, index) {
return {
value: item,
itemStyle: {
color: colorList[index]
}
};
});
chart.setOption({
title: {
text: 'Profit',
left: 'center'
},
tooltip: {},
xAxis: {
scale: true
},
yAxis: {},
series: [
{
type: 'custom',
renderItem: function (params, api) {
var yValue = api.value(2);
var start = api.coord([api.value(0), yValue]);
var size = api.size([api.value(1) - api.value(0), yValue]);
var style = api.style();
return {
type: 'rect',
shape: {
x: start[0],
y: start[1],
width: size[0],
height: size[1]
},
style: style
};
},
label: {
show: true,
position: 'top'
},
dimensions: ['from', 'to', 'profit'],
encode: {
x: [0, 1],
y: 2,
tooltip: [0, 1, 2],
itemName: 3
},
data: data
}
]
});
#main {
width: 600px;
height: 400px;
}
<html>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/5.3.2/echarts.min.js"></script>
<div id="main"></div>
</body>
</html>

How do I create a stacked horizontal bar chart with Chart.js in React?

I'm really struggling to find a clear answer to this question - especially in React. I'd like to create a stacked horizontal bar chart component for my React application. This is the type of chart I'm trying to create: https://codepen.io/pen. The code pasted below is what I've tried to use so far but it isn't rendering currently.
import React, { Component } from 'react';
import Chart from 'chart.js/auto';
export default class LineChart extends Component {
chartRef = React.createRef();
componentDidMount() {
const ctx = this.chartRef.current.getContext('2d');
new Chart(ctx, {
type: 'bar',
data: {
labels: [
'Sunday',
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday',
],
},
options: {
scales: {
yAxes: [
{
stacked: true,
},
],
},
},
datasets: [
{
data: [86, 114, 106, 106, 107, 111, 133],
label: 'Total',
borderColor: '#3e95cd',
backgroundColor: '#7bb6dd',
// fill: False,
},
{
data: [70, 90, 44, 60, 83, 90, 100],
label: 'Accepted',
borderColor: '#3cba9f',
backgroundColor: '#71d1bd',
// fill: False,
},
{
data: [10, 21, 60, 44, 17, 21, 17],
label: 'Pending',
borderColor: '#ffa500',
backgroundColor: '#ffc04d',
// fill: False,
},
{
data: [6, 3, 2, 2, 7, 0, 16],
label: 'Rejected',
borderColor: '#c45850',
backgroundColor: '#d78f89',
// fill: False,
},
],
});
}
render() {
return (
<div>
<canvas id="myChart" ref={this.chartRef} />
</div>
);
}
}
You are using V2 syntax of Chart.js while using V3. V3 has major breaking changis inclusing all scales are their own object. For all changes please read the migration guide.
When using objects for scales you get what you want:
const options = {
type: 'bar',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: 'orange'
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
backgroundColor: 'pink'
}
]
},
options: {
scales: {
y: {
stacked: true
},
x: {
stacked: true
}
}
}
}
const ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.js"></script>
</body>

how to hide x axis bar on apex chart?

I'm used react-apexcharts to make this below graph, i need to show a minimal view of a graph so i hide both x, y axis, legends, grid and everything, but this bar at the bottom not hiding. i couldn't find the right option on the documentation! is there any way to hide this?
This is the current output i'm getting!
const ProductivityGraph = () => {
const series = [{
name: 'Series A',
data: [23, 24, 25, 15, 25, 28, 38, 46],
},
{
name: 'Series B',
data: [20, 29, 37, 36, 44, 45, 50, 58],
},
];
const options:any = {
chart: {
toolbar: { // Hamburger menu at top
show: false,
},
height: 350,
type: 'line',
zoom: {
enabled: false,
},
},
dataLabels: {
enabled: false,
},
stroke: {
curve: 'smooth',
width: 2,
},
title: {
text: undefined,
align: 'left',
},
grid: {
show: false,
},
legend: {
show: false,
},
xaxis: {
show: false,
labels: {
show: false,
},
},
yaxis: {
show: false,
labels: {
show: false,
},
axisBorder: {
show: false,
},
axisTicks: {
show: false,
},
crosshairs: {
show: false,
},
tooltip: {
enabled: false,
},
},
};
return (
<div>
<ReactApexChart options={options} series={series} type="line" width={250} />
</div>
);
};
In your options replace xaxis with below one
xaxis: {
show: false,
labels: {
show: false
},
axisBorder: {
show: false
},
axisTicks: {
show: false
}
},

How to update data on zoom in apexchart

I am trying to find a way in the apex chart. By which if user zoom on the year graph then the user should be able to get month data when they zoom on month data this should show the day data.
But I am not able to figure out if its possible in apex chart or not.
This is how my graph look like right now.
import React from "react";
import ReactApexChart from "react-apexcharts";
interface StackedGraphProps {}
type SeriesType = {
name: string;
data: number[];
};
interface StackedGraphState {
series: SeriesType[];
options: any;
}
class StackedBarGraph extends React.Component<
StackedGraphProps,
StackedGraphState
> {
constructor(props: any) {
super(props);
this.state = {
series: [
{
name: "Marine Sprite",
data: [44, 55, 41, 37, 22, 43, 21],
},
{
name: "Striking Calf",
data: [53, 32, 33, 52, 13, 43, 32],
},
{
name: "Tank Picture",
data: [12, 17, 11, 9, 15, 11, 20],
},
],
options: {
chart: {
events: {
zoomed: function (chartContext: any, { xaxis, yaxis }) {
console.log("xAxis", xaxis, yaxis);
},
selection: function (chartContext: any, { xaxis, yaxis }) {
console.log("Selecton", xaxis, yaxis);
},
dataPointSelection: (
event: any,
chartContext: any,
config: any
) => {
console.log("datapoint", chartContext, config);
},
},
zoom: {
enabled: true,
type: "x",
autoScaleYaxis: false,
// zoomedArea: {
// fill: {
// color: "#90CAF9",
// opacity: 0.4,
// },
// stroke: {
// color: "#0D47A1",
// opacity: 0.4,
// width: 1,
// },
// },
},
type: "bar",
height: 350,
stacked: true,
},
toolbar: {
show: true,
},
plotOptions: {
bar: {
horizontal: false,
},
},
stroke: {
width: 1,
colors: ["#fff"],
},
grid: {
row: {
colors: ["#fff", "#f2f2f2f2"],
},
},
title: {
text: "",
},
xaxis: {
tickPlacement: "on",
categories: [2008, 2009, 2010, 2011, 2012, 2013, 2014],
labels: {
formatter: function (val: any) {
return val + "K";
},
},
},
yaxis: {
title: {
text: undefined,
},
},
tooltip: {
y: {
formatter: function (val: any) {
return val + "K";
},
},
},
fill: {
opacity: 1,
},
legend: {
position: "top",
horizontalAlign: "left",
offsetX: 40,
},
},
};
}
render() {
return (
<div id="chart">
<ReactApexChart
zoomEnabled={true}
options={this.state.options}
series={this.state.series}
type="bar"
height={350}
/>
</div>
);
}
}
export default StackedBarGraph;

Resources