List of all demos

React Pivot Table with amCharts

Flexmonster Pivot Table & Charts gently integrates with amCharts — a JavaScript library for interactive data visualization with a great choice of interactive charts.

This React dashboard example is built on some Kaggle data about the Cheese industry.

With our specially written connector for amCharts, your visualizations will become even more interactive: just change the slice on the pivot or filter the data, and see your charts immediately transform!

Overall Cheese Interest by Month

Creating React dashboards with amCharts and Flexmonster Pivot Table is easy and engaging: choose from a wide range of modern and bright charts and present your data most favourably.

Total Cheese Interest by Country

Icons made by Freepik from www.flaticon.com

Configure the React pivot grid with the data you need and instantly submit all the information to interactive charts: you will quickly identify all extremes and detect crucial points.

Feta Interest by Month
Feta Interest by Country

    import React, { Component } from "react";
    import * as FlexmonsterReact from "react-flexmonster";
    
    // Importing Flexmonster Connector for amCharts
    import "flexmonster/lib/flexmonster.amcharts.js";
    
    // amCharts imports
    import * as am5 from "@amcharts/amcharts5";
    import * as am5xy from "@amcharts/amcharts5/xy";
    import * as am5percent from "@amcharts/amcharts5/percent";
    import * as am5map from "@amcharts/amcharts5/map";
    import am5geodata_worldHigh from "@amcharts/amcharts5-geodata/worldHigh";
    import am5themes_Animated from "@amcharts/amcharts5/themes/Animated";
    import am5themes_Responsive from "@amcharts/amcharts5/themes/Responsive";
    
    class PivotTableDemo extends Component {
    
      constructor(props) {
        super(props);
        this.myRef = React.createRef();
        this.chartColors = [
          am5.color("#4CBF8B"),
          am5.color("#FFCD4C"),
          am5.color("#E8734C"),
          am5.color("#9875E3"),
          am5.color("#4C9EFF"),
          am5.color("#8ACFC3"),
          am5.color("#CD97E6"),
          am5.color("#F1D34C"),
          am5.color("#65D2E7"),
        ];
        this.cheeseColors = [am5.color("#FFE268"), am5.color("#FFCD4C"), am5.color("#FFB037")];
      }
    
      render() {
        return (
          <div className="App">
            <h1 className="page-title">Integrating with amCharts</h1>
    
            <div className="description-blocks first-description-block">
              <p>
                Extend Flexmonster’s visualization functionality by integrating with the amCharts
                library:{" "}
                <a href="https://www.flexmonster.com/doc/integration-with-amcharts/?r=rm_react" target="_blank" rel="noopener noreferrer" className="title-link">
                  Integration with amCharts
                </a>
                .
              </p>
            </div>
    
            <FlexmonsterReact.Pivot
              ref={this.myRef}
              toolbar={true}
              height={440}
              componentFolder="https://cdn.flexmonster.com/"
              report={{
                dataSource: {
                  type: "json",
                  filename: "data/demos/amcharts-demo-data.json",
                  mapping: {
                    Date: {
                      type: "date",
                    },
                    Country: {
                      type: "string",
                    },
                    id: {
                      type: "string",
                    },
                    CountryCode: {
                      type: "property",
                      hierarchy: "Country",
                    },
                    Feta: {
                      type: "number",
                    },
                    Mozzarella: {
                      type: "number",
                    },
                    "Parmigiano-Reggiano": {
                      type: "number",
                    },
                  },
                },
                slice: {
                  rows: [
                    {
                      uniqueName: "Date.Month",
                      filter: {
                        exclude: [
                          "date.month.[december]",
                          "date.month.[november]",
                          "date.month.[october]",
                        ],
                      },
                    },
                    {
                      uniqueName: "[Measures]",
                    },
                  ],
                  columns: [
                    {
                      uniqueName: "Country",
                    },
                  ],
                  measures: [
                    {
                      uniqueName: "Feta",
                      aggregation: "sum",
                      grandTotalCaption: "Feta",
                    },
                    {
                      uniqueName: "Mozzarella",
                      aggregation: "sum",
                      grandTotalCaption: "Mozzarella",
                    },
                    {
                      uniqueName: "Parmigiano-Reggiano",
                      aggregation: "sum",
                      grandTotalCaption: "Parmigiano-Reggiano",
                    },
                    {
                      uniqueName: "Fetas",
                      formula: 'sum("Feta")',
                      caption: "value",
                      active: false,
                    },
                  ],
                },
                options: {
                  grid: {
                    showHeaders: false,
                    showGrandTotals: "rows",
                  },
                  showAggregationLabels: false,
                },
              }}
              licenseFilePath="https://cdn.flexmonster.com/jsfiddle.charts.key"
              reportcomplete={this.reportComplete}
              customizeCell={this.customizeCell}
            />
            <div className="demo-box">
              <div className="demo-title">
                <strong>Overall Cheese Interest by Month</strong>
              </div>
              <div id="amcharts-stacked-container" className="chart-container"></div>
            </div>
            <div className="demo-box">
              <div className="demo-title">
                <strong>Total Cheese Interest by Country</strong>
              </div>
              <div id="amcharts-pictorial-container" className="chart-container"></div>
              <div>
                Icons made by{" "}
                <a href="https://www.freepik.com" title="Freepik">
                  Freepik
                </a>{" "}
                from{" "}
                <a href="https://www.flaticon.com/" title="Flaticon">
                  www.flaticon.com
                </a>
              </div>
            </div>
            <div className="demo-box">
              <div className="demo-title">
                <strong>Feta Interest by Month</strong>
              </div>
              <div id="amcharts-pie-container" className="chart-container"></div>
            </div>
    
            <div className="demo-box no-text-before no-text-after">
              <div className="demo-title">
                <strong>Feta Interest by Country</strong>
              </div>
              <div id="amcharts-map-container" className="chart-container"></div>
            </div>
          </div>
        );
      }
    
      reportComplete = () => {
        this.myRef.current.flexmonster.off(this.reportComplete);
        this.createStackedChart();
        this.createPictorialChart();
        this.createPieChart();
        this.createMapChart();
      };
    
      createStackedChart = () => {
        this.myRef.current.flexmonster.amcharts.getData(
          {},
          this.drawStackedChart,
          this.updateStackedChart
        );
      };
    
      drawStackedChart = (chartData, rawData) => {
        this.stackedChartRoot = am5.Root.new("amcharts-stacked-container");
    
        //Set themes
        this.stackedChartRoot.setThemes([am5themes_Animated.new(this.stackedChartRoot)]);
    
        let stackedChart = this.stackedChartRoot.container.children.push(
          am5xy.XYChart.new(this.stackedChartRoot, {})
        );
        stackedChart.get("colors").set("colors", this.chartColors);
        // Craete Y-axis
        var valueAxis = stackedChart.yAxes.push(
          am5xy.ValueAxis.new(this.stackedChartRoot, {
            renderer: am5xy.AxisRendererY.new(this.stackedChartRoot, {}),
            tooltip: am5.Tooltip.new(this.stackedChartRoot, {
              truncate: true,
              maxWidth: 200,
              tooltipText: "{category}",
            }),
          })
        );
    
        valueAxis.children.unshift(
          am5.Label.new(this.stackedChartRoot, {
            rotation: -90,
            text: "Queries",
            y: am5.p50,
            centerX: am5.p50,
          })
        );
    
        // Create X-Axis
        var categoryAxis = stackedChart.xAxes.push(
          am5xy.CategoryAxis.new(this.stackedChartRoot, {
            renderer: am5xy.AxisRendererX.new(this.stackedChartRoot, {
              minGridDistance: 20,
            }),
            categoryField: this.myRef.current.flexmonster.amcharts.getCategoryName(rawData),
            tooltip: am5.Tooltip.new(this.stackedChartRoot, {
              truncate: true,
              maxWidth: 200,
              tooltipText: "{category}",
            }),
          })
        );
    
        //Get xRendeder for axis configurations
        let xRenderer = categoryAxis.get("renderer");
    
        xRenderer.grid.template.setAll({
          location: 0,
        });
    
        const maxWidth = 200;
    
        xRenderer.labels.template.setAll({
          truncate: true,
          maxWidth: maxWidth,
          tooltipText: "{category}",
        });
    
        categoryAxis.events.on("boundschanged", function (ev) {
          let axis = ev.target;
          let cellWidth =
            axis.innerWidth() / (axis.getPrivate("endIndex") - axis.getPrivate("startIndex"));
          if (cellWidth < maxWidth) {
            xRenderer.labels.template.setAll({
              rotation: -45,
              horizontalCenter: "right",
              verticalCenter: "middle",
            });
          } else {
            xRenderer.labels.template.setAll({
              rotation: 0,
              horizontalCenter: "middle",
              verticalCenter: "top",
            });
          }
        });
    
        categoryAxis.data.setAll(chartData.data);
    
        for (let i = 0; i < this.myRef.current.flexmonster.amcharts.getNumberOfMeasures(rawData); i++) {
          // Create series
          let series = stackedChart.series.push(
            am5xy.ColumnSeries.new(this.stackedChartRoot, {
              xAxis: categoryAxis,
              yAxis: valueAxis,
              categoryXField: this.myRef.current.flexmonster.amcharts.getCategoryName(rawData),
              valueYField: this.myRef.current.flexmonster.amcharts.getMeasureNameByIndex(rawData, i),
              name: this.myRef.current.flexmonster.amcharts
                .getMeasureNameByIndex(rawData, i)
                .split(" ")
                .pop(),
              stacked: true,
            })
          );
    
          series.columns.template.setAll({
            tooltipText: "{name}, {categoryX}: {valueY}",
          });
    
          series.data.setAll(chartData.data);
        }
        stackedChart.set("cursor", am5xy.XYCursor.new(this.stackedChartRoot, {}));
      };
    
      updateStackedChart = (chartData, rawData) => {
        this.stackedChartRoot.dispose();
        this.drawStackedChart(chartData, rawData);
      };
    
      createPictorialChart = () => {
        this.myRef.current.flexmonster.amcharts.getData(
          {
            slice: {
              rows: [
                {
                  uniqueName: "Country",
                },
                {
                  uniqueName: "[Measures]",
                },
              ],
              measures: [
                {
                  uniqueName: "Fetas",
                  formula: 'sum("Feta")',
                  caption: "value",
                },
              ],
            },
          },
          this.drawPictorialChart,
          this.updatePictorialChart
        );
      };
    
      drawPictorialChart = (chartData, rawData) => {
        let iconPathValue = window.iconPath();
    
        // Create chart instance
        this.pictorialChartRoot = am5.Root.new("amcharts-pictorial-container");
        let pictorialChart = this.pictorialChartRoot.container.children.push(
          am5percent.SlicedChart.new(this.pictorialChartRoot, {
            layout: this.pictorialChartRoot.horizontalLayout,
          })
        );
    
        //Set themes
        this.stackedChartRoot.setThemes([am5themes_Animated.new(this.stackedChartRoot)]);
    
        //Create series
        let series = pictorialChart.series.push(
          am5percent.PictorialStackedSeries.new(this.pictorialChartRoot, {
            name: "Series",
            valueField: this.myRef.current.flexmonster.amcharts.getMeasureNameByIndex(rawData, 0),
            orientation: "horizontal",
            categoryField: this.myRef.current.flexmonster.amcharts.getCategoryName(rawData),
            alignLabels: true,
            svgPath: this.iconPathValue,
            maxWidth: 500,
            centerX: am5.percent(50),
            x: am5.percent(50),
          })
        );
        series.ticks.template.set("visible", false);
        series.labels.template.set("visible", false);
    
        series.get("colors").set("colors", this.cheeseColors);
    
        series.data.setAll(chartData.data);
    
        //Create legend
        var legend = pictorialChart.children.push(
          am5.Legend.new(this.pictorialChartRoot, {
            centerY: am5.percent(50),
            y: am5.percent(50),
            layout: this.pictorialChartRoot.verticalLayout,
          })
        );
    
        legend.markerRectangles.template.setAll({
          cornerRadiusTL: 10,
          cornerRadiusTR: 10,
          cornerRadiusBL: 10,
          cornerRadiusBR: 10,
        });
    
        legend.data.setAll(series.dataItems);
      };
    
      updatePictorialChart = (chartData, rawData) => {
        // Here you can add your own logic for updating the chart
      };
    
      createPieChart = () => {
        this.myRef.current.flexmonster.amcharts.getData(
          {
            slice: {
              rows: [
                {
                  uniqueName: "Date.Month",
                  filter: {
                    members: [
                      "date.month.[january]",
                      "date.month.[february]",
                      "date.month.[march]",
                      "date.month.[april]",
                      "date.month.[may]",
                      "date.month.[june]",
                    ],
                  },
                },
              ],
              measures: [
                {
                  uniqueName: "Feta",
                  aggregation: "sum",
                },
              ],
            },
          },
          this.drawPieChart,
          this.updatePieChart
        );
      };
    
      drawPieChart = (chartData, rawData) => {
        // Initialize the chart
        this.pieChartRoot = am5.Root.new("amcharts-pie-container");
        let pieChart = this.pieChartRoot.container.children.push(
          am5percent.PieChart.new(this.pieChartRoot, {
            numberFormatter: am5.NumberFormatter.new(this.pieChartRoot, {
              numberFormat: this.myRef.current.flexmonster.amcharts.getNumberFormatPattern(
                rawData.meta.formats[0]
              ),
            }),
          })
        );
    
        //Set themes
        this.stackedChartRoot.setThemes([am5themes_Animated.new(this.stackedChartRoot)]);
    
        // Create pie series
        let series = pieChart.series.push(
          am5percent.PieSeries.new(this.pieChartRoot, {
            name: "Series",
            y: am5.percent(-10),
            valueField: this.myRef.current.flexmonster.amcharts.getMeasureNameByIndex(rawData, 0),
            categoryField: this.myRef.current.flexmonster.amcharts.getCategoryName(rawData),
            alignLabels: true,
          })
        );
        series.get("colors").set("colors", this.chartColors);
        series.labels.template.set("text", "{category}: {value}");
    
        series.slices.template.adapters.add("radius", function (radius, target) {
          let dataItem = target.dataItem;
          let high = series.getPrivate("valueHigh");
    
          if (dataItem) {
            let value = target.dataItem.get("valueWorking", 0);
            return (radius * value) / high;
          }
          return radius;
        });
    
        series.slices.template.setAll({
          cornerRadius: 6,
          stroke: am5.color("#fff"),
          strokeWidth: 2,
          strokeOpacity: 1,
        });
    
        // Fill the chart with the data from Flexmonster
        series.data.setAll(chartData.data);
    
        //Create legend
        var legend = pieChart.children.push(
          am5.Legend.new(this.pieChartRoot, {
            centerX: am5.percent(50),
            x: am5.percent(50),
            y: am5.percent(95),
            centerY: am5.percent(100),
          })
        );
    
        const responsive = am5themes_Responsive.new(this.pieChartRoot);
    
        responsive.addRule({
          name: "Series",
          relevant: function (width, height) {
            return width <= 600;
          },
          applying: () => {
            series.ticks.template.set("visible", false);
            series.labels.template.set("visible", false);
          },
          removing: () => {
            series.ticks.template.set("visible", true);
            series.labels.template.set("visible", true);
          },
        });
    
        this.pieChartRoot.setThemes([responsive]);
    
        legend.data.setAll(series.dataItems);
      };
    
      updatePieChart = (chartData, rawData) => {
        // Here you can add your own logic for updating the chart
      };
    
      createMapChart = () => {
        this.myRef.current.flexmonster.amcharts.getData(
          {
            slice: {
              rows: [
                {
                  uniqueName: "id",
                },
              ],
              columns: [
                {
                  uniqueName: "[Measures]",
                },
              ],
              measures: [
                {
                  uniqueName: "Fetas",
                  formula: 'sum("Feta")',
                  caption: "value",
                },
              ],
            },
          },
          this.drawMapChart,
          this.updateMapChart
        );
      };
    
      drawMapChart = (chartData, rawData) => {
        this.mapChartRoot = am5.Root.new("amcharts-map-container");
    
        // Set themes
        this.mapChartRoot.setThemes([am5themes_Animated.new(this.mapChartRoot)]);
        // Create chart
        let mapChart = this.mapChartRoot.container.children.push(
          am5map.MapChart.new(this.mapChartRoot, {
            panX: "rotateX",
            panY: "none",
            valueField: this.myRef.current.flexmonster.amcharts.getMeasureNameByIndex(rawData, 0),
            homeZoomLevel: 9,
            maxZoomLevel: 9,
            minZoomLevel: 9,
            wheelY: "none",
            homeGeoPoint: {
              longitude: 12.496366,
              latitude: 42.399982,
            },
          })
        );
    
        // Create polygon series
        let polygonSeries = mapChart.series.push(
          am5map.MapPolygonSeries.new(this.mapChartRoot, {
            geoJSON: am5geodata_worldHigh,
            valueField: this.myRef.current.flexmonster.amcharts.getMeasureNameByIndex(rawData, 0),
            calculateAggregates: true,
            exclude: ["AQ"],
          })
        );
    
        polygonSeries.mapPolygons.template.setAll({
          tooltipText: "{name} {value}",
          fill: am5.color("#D3D3D3"),
        });
    
        polygonSeries.mapPolygons.template.events.on("pointerover", function (ev) {
          heatLegend.showValue(ev.target.dataItem.get("value"));
        });
    
        polygonSeries.events.on("datavalidated", () => {
          mapChart.goHome();
        });
    
        polygonSeries.set("heatRules", [
          {
            target: polygonSeries.mapPolygons.template,
            dataField: this.myRef.current.flexmonster.amcharts.getMeasureNameByIndex(rawData, 0),
            min: am5.color("#F1D34C"),
            max: am5.color("#4CBF8B"),
            key: "fill",
          },
        ]);
    
        polygonSeries.data.setAll(chartData.data);
    
        var heatLegend = mapChart.children.push(
          am5.HeatLegend.new(this.mapChartRoot, {
            target: polygonSeries.mapPolygons.template,
            orientation: "horizontal",
            width: am5.percent(100),
            y: am5.percent(100),
            centerY: am5.percent(100),
            startColor: am5.color("#F1D34C"),
            endColor: am5.color("#4CBF8B"),
            paddingBottom: 20,
            paddingTop: 20,
            paddingLeft: 20,
            paddingRight: 20,
          })
        );
    
        polygonSeries.events.on("datavalidated", function () {
          heatLegend.set("startValue", polygonSeries.getPrivate("valueLow"));
          heatLegend.set("endValue", polygonSeries.getPrivate("valueHigh"));
        });
      };
    
      updateMapChart = (chartData, rawData) => {
        // Here you can add your own logic for updating the chart
      };
    
      componentWillUnmount() {
        if (this.stackedChartRoot) {
          this.stackedChartRoot.dispose();
        }
        if (this.pictorialChartRoot) {
          this.pictorialChartRoot.dispose();
        }
        if (this.pieChartRoot) {
          this.pieChartRoot.dispose();
        }
        if (this.mapChartRoot) {
          this.mapChartRoot.dispose();
        }
      }
    
      customizeCell = (cell, data) => {
        if (data.hierarchy && data.type === "header") {
          if (data.hierarchy.caption === "Country" && data.member && data.member.properties) {
            let name = data.member.properties.CountryCode;
            let flag = `<i class="fm-icon ${data.expanded ? "fm-expanded-icon" : "fm-collapsed-icon"}" 
                  title="${data.expanded ? "Click to collapse" : "Click to expand"}"></i>
                  <img class="flag-icon" src="https://cdn.flexmonster.com/i/flags/${name.toLowerCase()}.svg">`;
            cell.text = `${flag}<span style="margin-left: 2px; line-height: 16px">${data.member.caption}</span>`;
            cell.addClass("fm-custom-cell");
          }
        }
      };
    }
    
    export default PivotTableDemo;
    
    body {
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
    }
    
    .chart-container {
      height: 450px;
    }
    
    .demo-box {
      background-color: #fafafa;
      position: relative;
      padding: 40px 30px 30px 30px;
      border: 1px solid #e9e9e9;
      margin-bottom: 20px;
      margin-top: 40px;
    }
    
    .demo-title {
      font-size: 18px;
      margin-bottom: 30px;
      white-space: nowrap;
      text-overflow: ellipsis;
      overflow: hidden;
      line-height: 24px;
    }
    
    .fm-custom-cell {
      display: flex !important;
      align-items: center !important;
      font-size: 12px !important;
    }
    
    .fm-custom-cell .flag-icon {
      width: 21px !important;
      height: 16px !important;
      margin-left: 0 !important;
      margin-right: 2px !important;
    }
    
    #fm-pivot-view .fm-grid-layout .fm-custom-cell.fm-expanded .fm-expanded-icon::before,
    #fm-pivot-view .fm-grid-layout .fm-custom-cell.fm-collapsed .fm-collapsed-icon::before {
      top: -2px;
      height: 16px;
    }
    
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8">
        <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
        <meta name="theme-color" content="#000000">
        <link rel="manifest" href="%PUBLIC_URL%/manifest.json">
        <title>Flexmonster & amCharts Demo</title>
        <!-- This file contains the iconPath() function needed for the pictorial chart -->
        <script src="https://cdn.flexmonster.com/data/demos/amcharts-iconPath.js"></script>
      </head>
      <body>
        <noscript>You need to enable JavaScript to run this app.</noscript>
        <div id="root"></div>
      </body>
    </html>
    

    Check this step-by-step integration with amCharts guide to start creating the best visualizations quickly.