We have updated Flexmonster Software License Agreement, effective as of September 30, 2024. Learn more about what’s changed.
List of all demos

Vue Pivot Table with amCharts

Seamlessly integrate Flexmonster Pivot with amCharts and add them to your Vue.js applications.

For the demo example, we took Kaggle data about the cheese industry to show how perfectly works the combination of Flexmonster Pivot & amCharts for the analytical dashboard for Vue application.

Use our special connector for amCharts to create interactive visualizations for your Vue project. With the help of connector the data is preprocessed into the array of objects format that you can easily use to show it in any chart type.

Overall Cheese Interest by Month

With the mix of a robust Vue pivot grid and a variety of stylish charts provided by the amCharts library, you can create interactive and responsive dashboards. Check out chart types that can be used for your Vue app.

Total Cheese Interest by Country

Icons made by Freepik from www.flaticon.com

All you need is just to configure the pivot table view according to your data logic and instantly transfer all the information to interactive charts.

Feta Interest by Month
Feta Interest by Country

    <template>
      <Pivot
        ref="pivot"
        componentFolder="https://cdn.flexmonster.com/"
        height="440"
        licenseFilePath="https://cdn.flexmonster.com/jsfiddle.charts.key"
        v-bind:report="report"
        v-bind:customizeCell="customizeCellFunction"
        v-bind:reportcomplete="reportcomplete"
      />
    
      <div class="demo-box">
        <div class="demo-title"><strong>Overall Cheese Interest by Month</strong></div>
        <div id="amcharts-stacked-container" class="chart-container"></div>
      </div>
    
      <div class="demo-box">
        <div class="demo-title"><strong>Total Cheese Interest by Country</strong></div>
        <div id="amcharts-pictorial-container" class="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 class="demo-box">
        <div class="demo-title"><strong>Feta Interest by Month</strong></div>
        <div id="amcharts-pie-container" class="chart-container"></div>
      </div>
    
      <div class="demo-box no-text-before no-text-after">
        <div class="demo-title"><strong>Feta Interest by Country</strong></div>
        <div id="amcharts-map-container" class="chart-container"></div>
      </div>
    </template>
    
    <script>
    import Pivot from "vue-flexmonster/vue3";
    import "flexmonster/flexmonster.css";
    
    // Importing Flexmonster Connector for amCharts
    import "flexmonster/lib/flexmonster.amcharts";
    
    // 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";
    
    const 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"),
    ];
    const cheeseColors = [am5.color("#FFE268"), am5.color("#FFCD4C"), am5.color("#FFB037")];
    
    export default {
      name: "PivotComponent",
      components: {
        Pivot,
      },
      data() {
        return {
          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",
                },
              ],
            },
            options: {
              grid: {
                showHeaders: false,
                showGrandTotals: "rows",
              },
              showAggregationLabels: false,
            },
          },
        };
      },
      methods: {
        reportcomplete() {
          this.$refs.pivot.flexmonster.off(this.reportComplete);
          this.createStackedChart();
          this.createPictorialChart();
          this.createPieChart();
          this.createMapChart();
        },
        createStackedChart() {
          this.$refs.pivot.flexmonster.amcharts.getData(
            {},
            this.drawStackedChart,
            this.updateStackedChart
          );
        },
        createPictorialChart() {
          this.$refs.pivot.flexmonster.amcharts.getData(
            {
              slice: {
                rows: [
                  {
                    uniqueName: "Country",
                  },
                  {
                    uniqueName: "[Measures]",
                  },
                ],
                measures: [
                  {
                    uniqueName: "Fetas",
                    formula: 'sum("Feta")',
                    caption: "value",
                  },
                ],
              },
            },
            this.drawPictorialChart,
            this.updatePictorialChart
          );
        },
        updateStackedChart(chartData, rawData) {
          this.stackedChartRoot.dispose();
          this.drawStackedChart(chartData, rawData);
        },
        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", 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.$refs.pivot.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.$refs.pivot.flexmonster.amcharts.getNumberOfMeasures(rawData); i++) {
            // Create series
            let series = stackedChart.series.push(
              am5xy.ColumnSeries.new(this.stackedChartRoot, {
                xAxis: categoryAxis,
                yAxis: valueAxis,
                categoryXField: this.$refs.pivot.flexmonster.amcharts.getCategoryName(rawData),
                valueYField: this.$refs.pivot.flexmonster.amcharts.getMeasureNameByIndex(rawData, i),
                name: this.$refs.pivot.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, {}));
        },
        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.$refs.pivot.flexmonster.amcharts.getMeasureNameByIndex(rawData, 0),
              orientation: "horizontal",
              categoryField: this.$refs.pivot.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", 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.$refs.pivot.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.$refs.pivot.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.$refs.pivot.flexmonster.amcharts.getMeasureNameByIndex(rawData, 0),
              categoryField: this.$refs.pivot.flexmonster.amcharts.getCategoryName(rawData),
              alignLabels: true,
            })
          );
          series.get("colors").set("colors", 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.$refs.pivot.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.$refs.pivot.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.$refs.pivot.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();
          });
    
          // Create polygon series
          polygonSeries.set("heatRules", [
            {
              target: polygonSeries.mapPolygons.template,
              dataField: this.$refs.pivot.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
        },
      },
      beforeUnmount() {
        if (this.stackedChart) {
          this.stackedChart.dispose();
        }
        if (this.pictorialChart) {
          this.pictorialChart.dispose();
        }
        if (this.pieChart) {
          this.pieChart.dispose();
        }
        if (this.mapChart) {
          this.mapChart.dispose();
        }
      },
      customizeCellFunction(cell, data) {
        if (
          data.hierarchy?.caption === "Country" &&
          data.type === "header" &&
          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");
        }
      },
    };
    </script>
    
    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="icon" href="/favicon.ico" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <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>
        <div id="app"></div>
        <script type="module" src="/src/main.js"></script>
      </body>
    </html>
    

    Read more about our integration with amCharts and easily start creating colorful and insightful visualizations.