Custom ChartSeriesLabels and Positioning ChartLegend

1 Answer 213 Views
Charts
Noor
Top achievements
Rank 1
Iron
Noor asked on 12 Apr 2022, 01:09 PM

I've been practicing the donut chart documentation but I'm having problems with custom ChartSeriesLabel and Custom ChartLegend, can you provide an example of the sample code I mean.

1 Answer, 1 is accepted

Sort by
0
Stefan
Telerik team
answered on 13 Apr 2022, 07:23 AM

Hello,

I can suggest checking the following forum thread that has examples for custom legends:

https://www.telerik.com/forums/kendo-ui-react-js-chart-legend-customization

This is how the customize the labels:

https://www.telerik.com/kendo-react-ui/components/charts/chart/elements/labels/#toc-customizing-the-content

Regards,
Stefan
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

Noor
Top achievements
Rank 1
Iron
commented on 17 Apr 2022, 03:38 PM

Hi Stefan, 

I have made code like this but it is not as expected, how do I make the mapping visible, whereas if the ChartSeriesItem in the mapping chart does not appear,
Please solve from the code
import React, {useState} from 'react';
import {Paper, Typography} from '@material-ui/core';
import {RectangleLegendIcon, SaturnusIcon} from 'assets/icons';
import {GridItem} from 'components/CustomGrid';
import styles from './ChartPredictionAnalytic.module.scss';
import {
  Chart,
  ChartLegend,
  ChartSeries,
  ChartSeriesItem,
  ChartSeriesLabels,
} from '@progress/kendo-react-charts';

const seriesData = [
  {
    value: 28,
    label: 'Order Received',
    visible: true,
  },
  {
    label: 'Hot Prospect',
    value: 7,
    visible: true,
  },
  {
    label: 'Warm Prospect',
    value: 4,
    visible: true,
  },
  {
    label: 'Cold Prospect',
    value: 6,
    visible: true,
  },
];

const seriesColors = ['#41b548', '#ff4151', '#ff9900', '#33a8fc'];

const ChartContainer = () => {
  const [series, setSeries] = useState(seriesData);
  const handleLegendItemClick = (e, seriesItem) => {
    let newSeries = series.map(item => {
      if (item.name === seriesItem.name) {
        item.visible = !item.visible;
      }
      return item;
    });
    setSeries(newSeries);
  };

  const labelContent = e => e.value;
  const sumValue = series.reduce(
    (sum, currentValue) => sum + currentValue.value,
    0
  );

  const donutCenterRender = () => (
    <span>
      <h3>{sumValue}</h3>
    </span>
  );

  return (
    <GridItem xs={12} sm={6}>
      <Paper className={styles['card']}>
        <div className={styles['section']}>
          <Chart
            donutCenterRender={donutCenterRender}
            seriesColors={seriesColors}
            onLegendItemClick={handleLegendItemClick}>
            <ChartSeries>
              <ChartSeriesItem
                data={series}
                startAngle={150}
                categoryField="label"
                field="value"
                type="donut"
                holeSize={50}>
                <ChartSeriesLabels
                  content={labelContent}
                  position="outsideEnd"
                  background="none"
                />
              </ChartSeriesItem>
            </ChartSeries>
            <ChartLegend visible={false} />
          </Chart>
          <div className={styles['custom-legend']}>
            {series.map((item, idx) => {
              const {label} = item;
              const styleLegend = {
                color: item.color,
                opacity: item.visible ? 1 : 0.5,
              };
              if (label === 'Order Received') {
                return (
                  <button
                    key={idx}
                    style={{...styleLegend}}
                    onClick={e => handleLegendItemClick(e, item)}
                    className={styles['custom-legend-child']}>
                    <RectangleLegendIcon className={item.color} />
                    <Typography className={styles['custom-legend-text']}>
                      {label}
                    </Typography>
                  </button>
                );
              } else if (label === 'Hot Prospect') {
                return (
                  <button
                    key={idx}
                    style={{...styleLegend}}
                    onClick={e => handleLegendItemClick(e, item)}
                    className={styles['custom-legend-child']}>
                    <RectangleLegendIcon className={item.color} />
                    <Typography className={styles['custom-legend-text']}>
                      {label}
                    </Typography>
                  </button>
                );
              } else if (label === 'Warm Prospect') {
                return (
                  <button
                    key={idx}
                    style={{...styleLegend}}
                    onClick={e => handleLegendItemClick(e, item)}
                    className={styles['custom-legend-child']}>
                    <SaturnusIcon />
                    <Typography className={styles['custom-legend-text']}>
                      {label}
                    </Typography>
                  </button>
                );
              } else if (label === 'Cold Prospect') {
                return (
                  <button
                    key={idx}
                    style={{...styleLegend}}
                    onClick={e => handleLegendItemClick(e, item)}
                    className={styles['custom-legend-child']}>
                    <SaturnusIcon />
                    <Typography className={styles['custom-legend-text']}>
                      {label}
                    </Typography>
                  </button>
                );
              }
            })}
          </div>
        </div>
      </Paper>
    </GridItem>
  );
};

export default ChartContainer;


Stefan
Telerik team
commented on 18 Apr 2022, 05:55 AM

Hello,

The important part of the custom legend is to dynamic render the series based on the clicked item. For the Donut Chart, we have to filter the data based on the visible field.
That means that here we have to pass only the series that have a field visible true:

              <ChartSeriesItem
                data={series} // filter series to only include the items with visible true. You can use standard array filtering 
Tags
Charts
Asked by
Noor
Top achievements
Rank 1
Iron
Answers by
Stefan
Telerik team
Share this question
or