<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ flexmonster - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ flexmonster - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sat, 23 May 2026 22:20:46 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/flexmonster/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Build an Analytical Dashboard with Next.js ]]>
                </title>
                <description>
                    <![CDATA[ If you work with data or plan to in the future, at some point you'll likely need to build a comprehensive analytics dashboard. Sharing data through charts is a great way to provide others with a clearer understanding of this information. Pairing it w... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-an-analytical-dashboard-with-nextjs/</link>
                <guid isPermaLink="false">67a3aa3efc0a24bff2e83e65</guid>
                
                    <category>
                        <![CDATA[ flexmonster ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ dashboard ]]>
                    </category>
                
                    <category>
                        <![CDATA[ analytics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ highcharts ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Stefan Muzyka ]]>
                </dc:creator>
                <pubDate>Wed, 05 Feb 2025 18:13:18 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1738347998117/46877c78-f5e5-4a94-954e-029b73b8f952.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you work with data or plan to in the future, at some point you'll likely need to build a comprehensive analytics dashboard.</p>
<p>Sharing data through charts is a great way to provide others with a clearer understanding of this information. Pairing it with a pivot table is also a smart approach, allowing you to view your data from different perspectives. And what if you could also aggregate data and customize charts to suit your needs?</p>
<p>In this guide, I’ve consolidated my knowledge on creating an analytics dashboard in Next.js using Flexmonster and Highcharts. To make it engaging, we’ll explore some interesting survey results about passenger flying etiquette. I hope you find it helpful. Let’s roll!</p>
<h2 id="heading-table-of-contents"><strong>Table of Contents</strong></h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-subject-area">The Subject Area</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-final-dashboard">The Final Dashboard</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-configure-highcharts-and-flexmonster-for-our-next-js-app">How to Configure Highcharts and Flexmonster for Our Next.js App</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-set-up-the-dashboard">How to Set Up the Dashboard</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-set-up-the-chart-configuration">How to Set Up the Chart Configuration</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-filling-up-the-dashboard-with-other-charts">Filling Up the Dashboard with Other Charts</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-connect-between-flexmonster-and-highcharts">Connect between Flexmonster and Highcharts</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-full-demo-link">Full demo link</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-wrapping-up">Wrapping up</a></p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ol>
<li><p>Install Next.js (installation guide <a target="_blank" href="https://nextjs.org/docs/app/getting-started/installation">here</a>)</p>
</li>
<li><p>In this project we’ll use the <code>flexmonster</code>, <code>react-flexmonster</code>, and <code>highcharts</code> libraries.</p>
</li>
</ol>
<pre><code class="lang-bash">npm i react flexmonster react-flexmonster highcharts highcharts-react-official
npm i -g flexmonster-cli
</code></pre>
<p>These are paid tools for sharing analytics but offer more options for working with data and customization. You can also use free/open-source alternatives like:</p>
<p><strong>Data/Analytics Libraries:</strong></p>
<ul>
<li><p><a target="_blank" href="https://github.com/nicolaskruchten/pivottable">PivotTable.js</a> — basic open-source pivot functionality</p>
</li>
<li><p><a target="_blank" href="https://www.npmjs.com/package/orb">Orb</a> — clean pivot UI with neat design</p>
</li>
<li><p><a target="_blank" href="https://www.webdatarocks.com/demos/react/pivot-table-demo/">WebDataRocks</a> — modern, free pivot table solution</p>
</li>
</ul>
<p><strong>Charts:</strong></p>
<ol>
<li><p><a target="_blank" href="https://nivo.rocks/">Nivo</a> — awesome free charts with D3 power</p>
</li>
<li><p><a target="_blank" href="https://www.chartjs.org/">Chart.js</a> — simple yet powerful canvas charts</p>
</li>
<li><p><a target="_blank" href="https://recharts.org/en-US/">Recharts</a> — React components for D3 charts</p>
</li>
</ol>
<h2 id="heading-the-subject-area"><strong>The Subject Area</strong></h2>
<p>Have you ever been curious about why people get so angry on planes with others' behavior? Or maybe you’re that person who’s… misbehaving? Have you wondered if it’s okay to bother your neighbors onboard, whether it’s for stepping out of your seat or asking for something?</p>
<p>Imagine: you board a plane with your friends, and you are seated apart, not all together. You want to change places with someone to sit near each other. How likely is it that the person next to you will consider this to be rude or unacceptable?</p>
<p>We can explore these questions through a <a target="_blank" href="https://fivethirtyeight.com/features/airplane-etiquette-recline-seat/">survey</a> on passenger etiquette conducted by ABC News. Our goal is to examine passengers' attitudes toward in-flight interactions and present our findings with charts and a pivot table. The complete survey data is sourced from <a target="_blank" href="https://github.com/fivethirtyeight/data/tree/master/flying-etiquette-survey">here</a>.</p>
<p>In this guide, I’ll highlight some intriguing correlations between different social groups and their perspectives on certain questions, such as:</p>
<ul>
<li><p>The impact of age and income on overall dissatisfaction.</p>
</li>
<li><p>What behaviors do passengers consider the rudest?</p>
</li>
<li><p>How does traveling with children affect the flight experience?</p>
</li>
<li><p>Which social groups tend to leave the flight most satisfied or dissatisfied?</p>
</li>
<li><p>Who is more likely to break flight rules?</p>
</li>
</ul>
<h2 id="heading-the-final-dashboard"><strong>The Final Dashboard</strong></h2>
<p>In this tutorial, we’ll create an interactive dashboard using Next.js, featuring a pivot table and several charts on the final page.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736375903721/ea1faca7-0bf3-4d32-83fc-5963035b832e.png" alt="The final dashboard" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-tools"><strong>Tools</strong></h3>
<p>I was looking for the tools that offer customizable and functional UI, wide range of chart types and pivot table features. So, I focused on <a target="_blank" href="https://www.flexmonster.com/">Flexmonster</a> for creating tables and <a target="_blank" href="https://www.highcharts.com/">Highcharts</a> for the charts. These tools offer user-friendly interfaces, extensive customization options, handle large datasets, and integrate with each other.</p>
<p>Now, let's delve into the process of integration.</p>
<h2 id="heading-how-to-configure-highcharts-and-flexmonster-for-our-nextjs-app"><strong>How to Configure Highcharts and Flexmonster for Our Next.js App</strong></h2>
<p>In order to create the analytical dashboard, you’ll need to install the libraries and configure your project. </p>
<h3 id="heading-1-define-the-nextjs-project">1. Define the Next.js project:</h3>
<pre><code class="lang-bash">npx create-next-app flexmonster-project --ts --app
<span class="hljs-built_in">cd</span> flexmonster-project
</code></pre>
<h3 id="heading-2-get-the-flexmonster-wrapper-for-react">2. Get the Flexmonster wrapper for React:</h3>
<pre><code class="lang-bash">flexmonster add react-flexmonster
</code></pre>
<p>Got it, libraries are now actually installed! Now, let’s move further, embedding them into the project.</p>
<h3 id="heading-3-import-flexmonster-styles-to-globalcss">3. Import Flexmonster styles to <code>global.css</code>:</h3>
<pre><code class="lang-bash">@import <span class="hljs-string">"flexmonster/flexmonster.css"</span>;
</code></pre>
<h3 id="heading-4-create-the-wrapper">4. Create the wrapper</h3>
<p>Now you’ll create the wrapper for your future pivot table that integrates Flexmonster and Highcharts. First, let’s create a <code>PivotWrapper.tsx</code> file.</p>
<pre><code class="lang-typescript"><span class="hljs-string">'use client'</span>
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> FlexmonsterReact <span class="hljs-keyword">from</span> <span class="hljs-string">"react-flexmonster"</span>;
<span class="hljs-keyword">import</span> Flexmonster <span class="hljs-keyword">from</span> <span class="hljs-string">'flexmonster'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"flexmonster/lib/flexmonster.highcharts.js"</span>;


<span class="hljs-comment">// take general Flexmonster parameters and some special for Next.js</span>
<span class="hljs-keyword">type</span> PivotProps = Flexmonster.Params &amp; {
    pivotRef?: React.ForwardedRef&lt;FlexmonsterReact.Pivot&gt;;
  }

<span class="hljs-comment">// pivotRef provides a reference to the Flexmonster instance for accessing the Flexmonster API.</span>
<span class="hljs-keyword">const</span> PivotWrapper: React.FC&lt;PivotProps&gt; = <span class="hljs-function">(<span class="hljs-params">{ pivotRef, ...params}</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> (
        &lt;FlexmonsterReact.Pivot
            {...params}
            ref={pivotRef}
        /&gt;
    )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> PivotWrapper;
</code></pre>
<h3 id="heading-5-import-the-wrapper">5. Import the wrapper</h3>
<p>Now, import the wrapper in the <code>analytical-dashboard/page.tsx</code> file. You can change the route name <code>analytical-dashboard</code> to your liking:</p>
<pre><code class="lang-typescript"><span class="hljs-string">"use client"</span>
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-keyword">type</span> { Pivot } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-flexmonster"</span>;
<span class="hljs-keyword">import</span> dynamic <span class="hljs-keyword">from</span> <span class="hljs-string">"next/dynamic"</span>;
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> Highcharts <span class="hljs-keyword">from</span> <span class="hljs-string">'highcharts'</span>;
<span class="hljs-keyword">import</span> HighchartsReact <span class="hljs-keyword">from</span> <span class="hljs-string">'highcharts-react-official'</span>;


<span class="hljs-comment">// Load the wrapper dynamically</span>
<span class="hljs-keyword">const</span> PivotWrap = dynamic(<span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">'@/app/PivotWrapper'</span>), {
    ssr: <span class="hljs-literal">false</span>,
    loading: <span class="hljs-function">() =&gt;</span> &lt;h1&gt;Loading Flexmonster...&lt;/h1&gt;
});


<span class="hljs-keyword">const</span> ForwardRefPivot = React.forwardRef&lt;Pivot, Flexmonster.Params&gt;(<span class="hljs-function">(<span class="hljs-params">props, ref?: React.ForwardedRef&lt;Pivot&gt;</span>) =&gt;</span>
    &lt;PivotWrap {...props} pivotRef={ref} /&gt;

)

ForwardRefPivot.displayName = <span class="hljs-string">'ForwardRefPivot'</span>;
</code></pre>
<p>By the way, Flexmonster supports dynamic loading for its tables, which provides a smooth experience when extracting large amounts of data. </p>
<h3 id="heading-6-place-your-pivot-wrapper-and-charts-into-the-dashboard">6. Place your pivot wrapper and charts into the dashboard.</h3>
<p>Let’s define a <code>WithHighcharts()</code> function to render our dashboard and work with its essential parts. First, we’ll initialize the <a target="_blank" href="https://react.dev/reference/react/useRef">ref object</a> for the pivot table to access it and its events. The charts will be created in the <code>createChart()</code> function, which runs when pivot data loads (in the <code>reportComplete</code> event). Finally, we return the <code>layout</code> function.</p>
<p>Add the code below to the <code>analytical-dashboard/page.tsx</code> file:</p>
<pre><code class="lang-typescript">
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">WithHighcharts</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> pivotRef: React.RefObject&lt;Pivot&gt; = React.useRef&lt;Pivot&gt;(<span class="hljs-literal">null</span>);

    <span class="hljs-keyword">const</span> reportComplete = <span class="hljs-function">() =&gt;</span> {
        pivotRef.current!.flexmonster.off(<span class="hljs-string">"reportComplete"</span>, reportComplete);
        createChart();
    }

    <span class="hljs-comment">// define and create charts on the page. Called when data loading is successfully completed</span>
    <span class="hljs-keyword">const</span> createChart = <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-comment">// here we will place charts rendering later</span>
    }

    <span class="hljs-keyword">return</span> (
        &lt;div className=<span class="hljs-string">"App"</span>&gt;
            &lt;div id=<span class="hljs-string">"pivot-container"</span> className=<span class="hljs-string">""</span>&gt;
              &lt;ForwardRefPivot
                ref={pivotRef}
                toolbar={<span class="hljs-literal">true</span>}
                beforetoolbarcreated={<span class="hljs-function"><span class="hljs-params">toolbar</span> =&gt;</span> {
                  toolbar.showShareReportTab = <span class="hljs-literal">true</span>;
                }}
                shareReportConnection={{
                  url: <span class="hljs-string">"https://olap.flexmonster.com:9500"</span>
                }}
                width=<span class="hljs-string">"100%"</span>
                height={<span class="hljs-number">600</span>}
                report = {{
                  dataSource: {
                    <span class="hljs-keyword">type</span>: <span class="hljs-string">"csv"</span>,
                    <span class="hljs-comment">// connect to our dataset</span>
                    filename: <span class="hljs-string">"https://query.data.world/s/vvjzn4x5anbdunavdn6lpu6tp2sq3m?dws=00000"</span>
                  }
                }}
                reportcomplete={reportComplete}
                <span class="hljs-comment">// your license key</span>
                licenseKey=<span class="hljs-string">"XXXX-XXXX-XXXX-XXXX-XXXX"</span>
              /&gt;
          &lt;/div&gt;

          <span class="hljs-comment">// here we will place chart layouts</span>
    )
}
</code></pre>
<h3 id="heading-7-run-the-application">7. Run the application:</h3>
<pre><code class="lang-bash">npm run build
npm start
</code></pre>
<p>If you are interested in a detailed integration of Flexmonster with <a target="_blank" href="https://www.flexmonster.com/doc/integration-with-next-js/">Next.js</a> and <a target="_blank" href="https://www.flexmonster.com/doc/integration-with-highcharts/">Highcharts</a>, you can check the complete documentation that I’ve linked here.</p>
<p>For now, we’ve set up a blank dashboard that’s ready to be populated with data. In the next section, I’ll walk you through the overall chart definition process and highlight some key considerations.</p>
<p>First, you’ll need to ensure that your charts update based on the filters applied to the grid. For that, you need to add the following snippet of code:</p>
<pre><code class="lang-typescript"> React.useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (pivotRef.current) {
        <span class="hljs-keyword">const</span> pivot = pivotRef.current.flexmonster;

        <span class="hljs-comment">// Trigger the chart update when data changes</span>
        pivot.on(<span class="hljs-string">'dataChanged'</span>, createChart);
        pivot.on(<span class="hljs-string">'filterclose'</span>, createChart);


        <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
          pivot.off(<span class="hljs-string">'dataChanged'</span>, createChart);
          pivot.off(<span class="hljs-string">'filterclose'</span>, createChart);
        }
    }
}, [pivotRef]);
</code></pre>
<p>In this case, Next.js tracks the <a target="_blank" href="https://www.flexmonster.com/api/filterclose/?r=stfc2"><code>filterClose</code></a> event and triggers the <code>createChart()</code> function, which updates the charts. Unfortunately, there is no event for filter changes, only for filter pop-up window opening/closing. So, I used the event that triggers on filter pop-up window closing, as I usually use it for applying filters. You can read more about Flexmonster events <a target="_blank" href="https://www.flexmonster.com/api/events/?r=stfc2">here</a>.</p>
<h2 id="heading-how-to-set-up-the-dashboard"><strong>How to Set Up the Dashboard</strong></h2>
<p>To get started, let's get acquainted with our pivot table. The upcoming charts will draw information directly from it, so it's a good idea to first understand how the dashboard works.</p>
<p>In the previous step, we already created a default grid. If you run it now, it will look like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736375968187/a71c06db-1f6d-4d0a-ad0e-4b4457d5f575.png" alt="The default grid of the Flexmonster pivot table" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>It simply displays some default data from the dataset. Not bad, but we want to configure more representative data and explore the full potential of Flexmonster.</p>
<h3 id="heading-1-configure-the-pivot-table"><strong>1. Configure the pivot table</strong></h3>
<p>The main buttons that allow you to configure what and how the data is displayed in the table are <strong>Format</strong>, <strong>Settings</strong>, and <strong>Fields</strong>. We’ll start with Fields.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736376015936/122a95ed-98aa-4128-9c18-d31e95be4437.gif" alt="GIF: connecting dataset fields to the grid" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>By opening the Fields tab, you can select which columns from your dataset you want to display in the table. What shall we choose?</p>
<p>Hmm… It seems interesting to see the percentage distribution of respondents of different ages across various regions. Some polled regions likely have more older respondents, some younger, and others may have a balanced mix. This is more about analyzing the composition of the survey itself, but it’s a good start.</p>
<p>To achieve this, select the necessary fields in Rows and Columns. Next, choose the function to calculate the final values. There are quite a few options, but we’ll go with <strong>Percentage of column</strong>. As a result, you’ll get the percentage distribution of respondents of specific age groups in each region.</p>
<p>Here we go:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736376040585/181e9f1d-38ed-4731-8700-bbee02a7bbd5.png" alt="Location and Age grid with raw data" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Alright, let’s tidy up this table a bit. We’ll keep just one decimal place, which you can do in the <strong>Format</strong> tab like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736378089026/8e853863-86ee-40a8-be66-6fa9c339f164.png" alt="Format tab" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>It’s quite simple: select the required field (in this case, there will only be one) in the <strong>Choose Value</strong> field and set <strong>Decimal Places</strong> to 1.</p>
<p>We’ll also remove the <strong>Grand Totals</strong> since they are unnecessary for our purposes. You can do this in the <strong>Settings</strong> tab:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736378067956/a66dd0f9-0589-473e-b0af-c9c6bfe0d0b1.png" alt="Layout options" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Finally, we’ll want to remove blank responses. This is a feature of the selected dataset – some respondents chose not to answer certain questions, leaving the response field blank. For our analysis, this data is unnecessary, so we’ll filter it out.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736376126270/4bc3f72c-5e68-4e39-b1da-19f179ad2e4f.gif" alt="GIF: filtering data" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>And here’s how the table looks now. Quite neat!</p>
<h3 id="heading-2-conditional-formatting"><strong>2. Conditional Formatting</strong></h3>
<p>Now we want to set up conditional formatting to highlight standout data. The table is already configured, but adding visual cues will make the information easier to interpret. Fortunately, Flexmonster supports this feature, so let’s use it.</p>
<p>Here’s my idea: we want to identify areas where the distribution of respondents by age is uneven. We have four age ranges: youngsters (18-29), millennials (30-44), Gen X (45-59), and seniors (60+). In a balanced distribution, each age group should account for 100/4 = 25% (with a margin of ±2÷3%).</p>
<p>Here’s the plan:</p>
<ul>
<li><p>22-27%: Average distribution (within range).</p>
</li>
<li><p>17-22% or 27-32%: slightly underrepresented or overrepresented.</p>
</li>
<li><p>&lt;17% or &gt;32%: strongly underrepresented or overrepresented.</p>
</li>
</ul>
<p>In the <strong>Format</strong> tab, select <strong>Conditional Formatting</strong> and add conditions. Define the range with the value it applies to, and the highlight color. As a result, you’ll get a table that looks like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736376163028/c7c28901-30b4-49f7-b146-2ed5e6dbfc9f.gif" alt="GIF: Conditional formatting" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>According to the table, most respondents are middle-aged. In some cases, they make up the majority of polled people of their region. The most unbalanced distribution is around the East South Central and Middle-Atlantic states. There are overrepresented in one age group, and underrepresented in others. </p>
<p>Awesome! We’ve explored the Flexmonster table. Beyond displaying data, it can also filter data for all our upcoming charts. Let’s move on to setting up the charts, and I’ll show you how the table can influence its data.</p>
<h2 id="heading-how-to-set-up-the-chart-configuration"><strong>How to Set Up the Chart Configuration</strong></h2>
<p>In this section, we’ll create pie, bar, column, area, and line charts. It sounds like a lot, but Highcharts provides a wide range of <a target="_blank" href="https://www.highcharts.com/docs/chart-and-series-types/chart-types">chart types</a>. You can also customize them to your liking.</p>
<p>First, we’ll create a <a target="_blank" href="https://www.highcharts.com/docs/chart-and-series-types/pie-chart">pie chart</a> showing location distribution of passengers. While a basic pie chart would typically be a circle, I’m opting for a donut chart instead. This example demonstrates the common chart configuration process. For other charts, simply modify the chart type, rows, and measures. You can also play with dataset fields and chart types to your liking.</p>
<h3 id="heading-1-insert-highcharts-into-the-page"><strong>1. Insert Highcharts into the page.</strong></h3>
<p>First, move down to the <code>return()</code> section. at the bottom, leave a free place for the chart layouts. So, here we’ll insert the first <code>&lt;div&gt;</code> block to store the future pie chart. As it’s about the etiquette of passengers onboard, let’s assign it an id of <code>chart-location-distribution</code>: </p>
<pre><code class="lang-typescript">&lt;div className=<span class="hljs-string">"chart-item"</span>&gt;
  &lt;h2&gt;Location Distribution&lt;/h2&gt;
  &lt;div id=<span class="hljs-string">"chart-location-distribution"</span>&gt;&lt;/div&gt;
&lt;/div&gt;
</code></pre>
<h3 id="heading-2-define-the-chart-options"><strong>2. Define the chart options.</strong></h3>
<p>Let’s move on to the <code>createChart()</code> function. At the moment, it’s empty. To define the chart, paste <a target="_blank" href="https://www.flexmonster.com/doc/integration-with-highcharts/?r=stfc2"><code>pivotRef.current!.flexmonster.highcharts?.getData()</code></a> into it. It gets three parameters inside: <code>chart options</code>, <code>callbackHandler</code>, and <code>updateHandler</code>.</p>
<pre><code class="lang-typescript">pivotRef.current!.flexmonster.highcharts?.getData(
    <span class="hljs-comment">// getting the current slice of data from the grid to apply filters to the chart</span>
    <span class="hljs-keyword">const</span> gridSlice = pivotRef.current!.flexmonster.getReport()?.slice <span class="hljs-keyword">as</span> Flexmonster.Slice
        {
            <span class="hljs-keyword">type</span>: <span class="hljs-string">'pie'</span>,
            slice: {
                rows: [{ uniqueName: <span class="hljs-string">'Location (Census Region)'</span>, }],
                measures: [
                    {
                        uniqueName: <span class="hljs-string">'RespondentID'</span>,
                        aggregation: <span class="hljs-string">'count'</span>,
                    },
                ],
                <span class="hljs-comment">// apply current grid filters to the chart</span>
                reportFilters: gridSlice.reportFilters
            },
        },
    <span class="hljs-comment">// ...</span>
    <span class="hljs-comment">// in the next code section, I describe last two parameters</span>
    <span class="hljs-comment">// to be continued</span>
)
</code></pre>
<p>Since we pass chart options as Flexmonster.Slice from <code>getReport()</code>, the data updates dynamically from the grid. The <code>Slice</code> object specifies which data sample to display on the chart by selecting from the dataset. You can read more about the properties of grid slices <a target="_blank" href="https://www.flexmonster.com/api/slice-object/">here</a>.</p>
<p>You can customize the chart by changing data properties inside the <code>callbackHandler</code> parameter. Down below, we’ll create a custom donut chart by doing this:</p>
<pre><code class="lang-typescript">pivotRef.current!.flexmonster.highcharts?.getData(
  <span class="hljs-comment">// ...</span>
  <span class="hljs-comment">// continuing of configuring chart</span>
  <span class="hljs-comment">// chart options parameter defined in previous code section</span>

  (data: <span class="hljs-built_in">any</span>) =&gt; {  
        <span class="hljs-comment">// Define the chart configuration within the data object</span>
        data.chart = {
            <span class="hljs-keyword">type</span>: <span class="hljs-string">'pie'</span>,
        };

        data.title = {
            text: <span class="hljs-string">'Aggregated Survey Responses'</span>
        };

        data.legend = {
            layout: <span class="hljs-string">'horizontal'</span>,
            align: <span class="hljs-string">'center'</span>,
            verticalAlign: <span class="hljs-string">'bottom'</span>, 
            x: <span class="hljs-number">0</span>,
            y: <span class="hljs-number">10</span>, 
        }

        data.plotOptions = {
            pie: {
                innerSize: <span class="hljs-string">'50%'</span>,
                dataLabels: {
                    enabled: <span class="hljs-literal">true</span>,
                    format: <span class="hljs-string">'&lt;b&gt;{point.name}&lt;/b&gt;: {point.percentage:.1f} %'</span>,
                },
            },
        };

        Highcharts.chart(<span class="hljs-string">'chart-location-distribution'</span>, data);
    },
    <span class="hljs-function">(<span class="hljs-params">data: <span class="hljs-built_in">any</span></span>) =&gt;</span> {
        Highcharts.chart(<span class="hljs-string">'chart-location-distribution'</span>, data);
    }
)
</code></pre>
<p><strong>Note!</strong> You should change <code>data</code> <strong>before</strong> it passes to the <code>Highcharts.chart()</code> function as a parameter.</p>
<h3 id="heading-3-completed-location-distribution-pie-chart"><strong>3. Completed Location Distribution Pie Chart</strong></h3>
<p>The chart shows that the most common passengers on this airline are locals from the Pacific, and the least common passengers are from the East South Central states. This is quite interesting. It might be because the Pacific region includes large cities such as San Francisco, Los Angeles, Seattle, and Portland, while the East South Central region includes states like Mississippi and Alabama, which have smaller populations and population density.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736376204736/797d7944-cc61-454f-9cbc-f3d9d2d24e43.png" alt="'Location distribution' pie chart" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h2 id="heading-filling-up-the-dashboard-with-other-charts"><strong>Filling Up the Dashboard with Other Charts</strong></h2>
<p>Now, let’s create the remaining charts following the same process – adjusting the chart <code>type</code>, <code>slice</code> options, and <code>callbackHandler</code> functions for each diagram. You can find the full chart configuration of each chart at <a class="post-section-overview" href="#heading-full-demo-link">the end of the guide</a> on my GitHub.</p>
<h3 id="heading-1-frequency-of-using-airlines-distributed-by-locations"><strong>1. Frequency of using airlines distributed by locations</strong></h3>
<p>Here we can see with a <a target="_blank" href="https://www.highcharts.com/docs/chart-and-series-types/column-chart">stacked column chart</a> how often people from different regions fly.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736376209953/a1fd26e5-c7eb-4612-a376-dcb61315d61a.png" alt="'Frequency of using airlines distributed by locations' stacked column chart" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>The average passenger from regions across the board tend to fly infrequently, with most flying once a year. Overall, the trend suggests that flying habits are influenced by regional factors, with occasional travel being more common than frequent flying. An interesting fact is that many of the polled people here have never flown! (How did they get into this poll?!)</p>
<h3 id="heading-2-who-breaks-the-rules-on-board"><strong>2. Who breaks the rules on board?</strong></h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736376226439/2c8c093e-e4b3-4964-9097-5110b6813f6f.png" alt="'Frequency of travel to rule violations' bar chart" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Tricky question, isn’t it? We all know that smoking and using electronics are prohibited on board. But not everyone follows these rules, and fewer will admit to breaking them.</p>
<p>Still, pollsters managed to gather some insights about rule violations. The <a target="_blank" href="https://www.highcharts.com/docs/chart-and-series-types/bar-chart">bar chart</a> above reveals a trend: frequent flyers tend to neglect the rules, while those who fly less often are more likely to follow them.</p>
<p>From my own experience, your first flights are stressful, and you typically try not to disrupt the delicate balance of the plane. Every rule feels crucial, almost sacred. But regular fliers don’t seem to think this way.</p>
<h3 id="heading-3-ease-of-communication-depending-on-age"><strong>3. Ease of communication depending on age</strong></h3>
<p>The <a target="_blank" href="https://www.highcharts.com/docs/chart-and-series-types/line-chart">line chart</a> below shows that age influences your ease of communication with strangers, with middle-aged people often feeling more comfortable initiating conversations.</p>
<p>Personally, I always enjoy befriending or communicating with strangers, as it brings a sense of connection. But for many people, especially on board a flight, approaching strangers can be difficult, with older passengers often feeling more hesitant to engage.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736376241508/ebe08ce7-bcb9-4e08-8296-2ad4c953c4ac.png" alt="'Age and ease of communication' line chart" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>People aged 30-44 are most comfortable communicating with strangers during flights. In contrast, both younger passengers (under 30) and older passengers (60+) view excessive communication as rude and prefer to keep to themselves during the journey.</p>
<h3 id="heading-4-do-men-consider-bringing-children-onboard-ruder-than-women"><strong>4. Do men consider bringing children onboard ruder than women?</strong></h3>
<p>I thought that men might be more affected by unruly children in different spaces, so I decided to check that. The question asked was, ‘Is it rude to bring unruly children on board?’ The options were ‘No, not at all,’ ‘Yes, somewhat rude,’ and ‘Yes, it’s rude.’ So, I built another pie chart to see the relationship.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736376256453/7d8b1e74-6c1a-45b1-8601-84dc4d806382.png" alt="Gender distribution of 'Yes, very rude' responses to question: 'Is it rude to bring unruly babies oboard?' pie chart" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Almost two-thirds of men chose the ‘Yes, rude’ option, while fewer women selected that answer.</p>
<h3 id="heading-5-peoples-demands-of-others-and-themselves"><strong>5. People's demands of others and themselves.</strong></h3>
<p>People often hold double standards, considering certain behaviors rude when done by others but not when they engage in those behaviors themselves. One of the most painful issues onboard is the mess created by reclining seats, which can affect the comfort of other passengers. This led me to research how people feel about reclining seats and how frequently they engage in the practice.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736376314682/b686dc8d-ee38-4e98-b5db-6e8397d9f5c5.png" alt="'Seat recline and seat obligation' stacked column chart" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>An interesting correlation emerged in two key points: the most outraged passengers are often those who do not recline their seats and are usually the ones who can't tolerate when others do so. Also, there is always a small group of people who recline their seats regularly but are willing to argue with others about the same action.</p>
<h3 id="heading-6-which-age-group-tends-to-be-outraged"><strong>6. Which age group tends to be outraged?</strong></h3>
<p>The <a target="_blank" href="https://www.highcharts.com/docs/chart-and-series-types/area-chart">area chart</a> covers all the questions about what passengers consider rude, allowing us to observe how different age groups respond to various situations. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736376320810/9a9a31b8-565a-4044-b221-7d40f8fdf32e.gif" alt="'Age and 'Yes, it is rude' responds' area chart" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Interestingly, the most outraged responses are regarding babies onboard and people waking up to walk around the plane. Youngsters are most outraged by reclining seats, while passengers aged 30-44 tend to be more upset about people walking to the bathroom. Older passengers are also concerned about reclining seats.</p>
<p>The least outraged responses are about communicating with others and moving to unsold seats, indicating that gadgets haven’t completely stolen the value of live communication.</p>
<p>I attached links to the Highcharts documentation for each chart, but additional charts are available. You can inspect them <a target="_blank" href="https://www.highcharts.com/docs/chart-and-series-types/chart-typeshttps://www.highcharts.com/docs/chart-and-series-types/chart-types">here</a>.</p>
<h2 id="heading-how-to-sync-data-between-flexmonster-and-highcharts">How to Sync Data Between Flexmonster and Highcharts</h2>
<p>Let’s recall the earlier section on <a class="post-section-overview" href="#heading-2-define-the-chart-options">configuring chart options</a>. Here, adding the <code>reportFilters</code> field to the slice object enables data synchronization across all dashboard elements, from pivot table to charts.</p>
<p>To filter dashboard data, add fields to <strong>Report Filters</strong> in the <strong>Fields</strong> tab and observe chart updates. For example, filtering Location values affects the pie chart and column chart since they use Location data.</p>
<p>You can try it out by adding other rows to Report Filters and directly influence the appearance of your charts.</p>
<h2 id="heading-full-demo-link"><strong>Full Demo Link</strong></h2>
<p><img src="https://noname-hub.com/imgs/final.gif" alt="final" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>You can check out the full Next.js demo app and the dashboard yourself <a target="_blank" href="https://github.com/StefanErrorerko/AnalyticalDashboardFlyingEtiquette">here</a>.</p>
<h2 id="heading-wrapping-up"><strong>Wrapping up</strong></h2>
<p>In this tutorial, we built an interactive statistical dashboard, analyzed the subject matter, and processed the dataset. Along the way, we explored key configuration specifics for the libraries we used: Highcharts and Flexmonster. We then populated the dashboard with charts and demonstrated how to interact with it effectively.</p>
<p>I aimed to highlight a diverse and engaging dataset to make the process more interesting. I hope this guide serves as a helpful resource for building analytical dashboards in Next.js. Best of luck with your projects!</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
