Display a fixed three levels of highchart Sunburst upon each click in Angular8

Looking to create a dynamic sunburst highchart that displays three levels at a time while allowing interactive drilling. For instance, if there are 5 levels, the chart should initially show the first three levels. When clicking on level 3, levels 2, 3, and 4 should be displayed, and so on.

Below is the AngularV8 implementation:

.html file

<div class="kt-widget14__chart" style="min-height:300px;">
   <div class="chartjs-size-monitor-new">
       <highcharts-chart [Highcharts]="highcharts" [options]="company360SunburstOptions"
           style="width: 100%; height: 100%; display: block;">
       </highcharts-chart>
   </div>
</div>

.ts file


this.myService.getData().subscribe(result => {
            this.chartOptions.series[0].data = result;
            this.chartOptions.series[0].point = {
                events: {
                    click: (function (event) {
                        that.poinClicked(data);
                    })
                }
            };
        });

    chartOptions = {
        chart: {
            type: "sunburst",
            height: '100%',
        },
        credits: {
            enabled: false
        },
        exporting: { enabled: false },
        title: {
            text: ''
        },
        subtitle: {
            text: ''
        },
        plotOptions: {
            series: { // or general options: "series: { ... }"
                dataLabels: {
                    format: '{point.name}',
                    filter: {
                        property: 'innerArcLength',
                        operator: '>',
                        value: 16
                    },
                    enabled: true,
                    style: {
                        textShadow: false
                    }
                },
                animation: false
            }
        },
        series: [{
            type: "sunburst",
            data: [],
            allowDrillToNode: true,
            cursor: 'pointer',
            point: {},
            levels: [{
                level: 1,
                levelSize: {
                    units: 'percentage',
                },
                hidden: false,
                dataLabels: {
                    enabled: true
                }
            }, {
                level: 2,
                hidden: false,
                dataLabels: {
                    enabled: true
                }
            }, {
                level: 3,
                hidden: true,
                dataLabels: {
                    enabled: false
                },
                levelSize: {
                    value: 0
                }
            }, {
                level: 4,
                hidden: true,
                dataLabels: {
                    enabled: false
                },
                levelSize: {
                    value: 0
                }
            }]
        }],
        tooltip: {
            enabled: false
        }
    };

pointClicked() {

   let level = data['Level'];
   level = level + 1;
   if (level == 1) {
      this.sunburstShowLevels([1,2])
   } else if (level == 2) {
       this.sunburstShowLevels([1,2,3])
   } else if (level == 3) {
       this.sunburstShowLevels([2,3,4])
   }
}

sunburstShowLevels(levelIdList) {
   // Will get a list of levelIds that should be display
   let levels = this.chartOptions.series[0].levels; // Whole levels object
   let newLevels = [];
   for (var index=0; index<levels.length; index++) {
       var level = levels[index];
       if (levelIdList.includes(level['level'])) {
          // Then show it
          level.hidden = false; // set flag
          level['levelSize'] = {value: 1};
          level['dataLabels'] = {enabled: true}
       } else {
           level.hidden = true; // set flag
          level['levelSize'] = {value: 0};
          level['dataLabels'] = {enabled: false}
       }
       newLevels.push(level);
    }
}

Although the code works correctly in displaying the desired levels upon clicking, an issue arises where two clicks are required for the functionality to take effect. For example, when clicking on the second level, it initially shows only level 2 before displaying levels 1, 2, and 3 after the second click.

Challenge

In conclusion, the goal is to efficiently display specific levels upon each click without the need for multiple clicks to trigger the desired behavior. Seeking alternative suggestions or improvements to streamline this process. Grateful for any assistance.

Thank you in advance.

Answer №1

I came up with a new approach to achieve this by utilizing the series.update functionality for updating level options.

Check out the demo here: https://jsfiddle.net/BlackLabel/zrt4m13g/

Below is the code snippet:

point: {
  events: {
    click(e) {
      let series = this.series,
        clickedLevel = this.node.level,
        currentOptions = series.userOptions.levels;

      for (let i of currentOptions) {
        if (clickedLevel !== 0 /*or 1 */ && clickedLevel !== currentOptions.length) {
          if (i.level === clickedLevel || i.level === clickedLevel + 1 || i.level === clickedLevel - 1) {
            i.levelSize = {
              value: 1
            }
          } else {
            i.levelSize = {
              value: 0
            }
          }
          i.dataLabels = {
              rotationMode: 'parallel',
              filter: {
                property: 'outerArcLength',
                operator: '>',
                value: 64
              },
              enabled: true
          }
        }
      }

      series.update({
        levels: currentOptions
      })
    }
  }
},

For more information, refer to the API documentation: https://api.highcharts.com/highcharts/series.sunburst.levelSize

Explore the Series API update method here: https://api.highcharts.com/class-reference/Highcharts.Series#update

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Testing chai: verifying the inclusion of object types in an array

I am currently in the process of testing a Node.js/Typescript application. My goal is to have my function return an array consisting of objects. These objects should adhere to the following type: type myType = { title: string; description: string; ...

How can I completely alter the content of aaData in jquery.dataTables?

Looking to completely change the content of a datatable purely from a javascript perspective, without relying on Ajax calls. I've attempted using the following script: oTable.fnClearTable(); oTable.fnAddData(R); oTable.fnAdjustColumnSizin ...

Unable to properly execute Fetch Delete Request

When using the Fetch API, I am sending this request: const target = e.currentTarget; fetch(target.href, { method: 'delete', }) .then(res => console.log(22)) .catch(err => console.log(err)); In addition, here is the middleware that manag ...

You are limited to storing only up to 2 items in the localStorage

My goal is to save items in local storage as an array of objects. Initially, it works perfectly and stores the first element in local storage as needed. However, I am facing an issue where I cannot store more than one element. Below is the code block that ...

What is the best way to manage user sessions for the Logout button in Next.js, ensuring it is rendered correctly within the Navbar components?

I have successfully implemented these AuthButtons on both the server and client sides: Client 'use client'; import { Session, createClientComponentClient } from '@supabase/auth-helpers-nextjs'; import Link from 'next/link'; ...

modifying the href attribute of a tag is determined by the value of window

I'm working on a jQuery snippet that detects the current window's URL and, depending on the href value of the window, changes the href of an anchor tag. Here's what my code looks like so far: (function($) { "use strict"; $(document).re ...

What is the method for configuring environment variables in the Lumber framework?

Installing Lumber CLI npm install -g lumber-cli -s Next, lumber generate "adminpanel_test" --connection-url "mysql://root@localhost:3306/admin-dev" --ssl "false" --application-host "localhost" --application-port "3310" Error: lumber is not recognized a ...

Template for typed variable - `ng-template`

How can the parent component correctly identify the type of let-content that is coming from ngTemplateOutletContext? The current usage of {{content.type}} works as expected, but my IDE is showing: unresolved variable type Is there a way to specify the ...

Exploring JSON parsing using javascript?

I'm currently attempting to work through this webRTC example and have encountered an issue that appears to be minor in nature... The if statement consistently fails to return true, despite the fact that the console message indicates that the property ...

Steps for updating text within an object in Angular

details = [ { event: "02/01/2019 - [Juan] - D - [Leo]", point: 72 }, { event: "02/01/2019 - [Carlo] - N - [Trish]", point: 92 } ]; I am attempting to modify the text within the titles that contain - N - or - D - The desired outcom ...

Having trouble executing the npm start command for ReactJS

Below is the code snippet from my file named server.js if(process.env.NODE_ENV !== 'production') { require('dotenv').parse() } const express = require('express') const app = express() const expressLayouts = require(' ...

Propagating numerical values through iterative iterations

I am currently facing an issue with passing values as props to a component using the forEach method in JavaScript. In addition to passing the existing values from an array, I also want to send another value that needs to be incremented by 1 for each iterat ...

Browserify - combine external modules into a single bundle

I am a complete beginner in the world of browserify. I recently discovered this interesting module called peer-file, which allows for file transfer between two browsers. After reading the Usage section in its readme, I realized I needed to include the scri ...

Communication between components through a shared service

Imagine you find yourself in one component and need to trigger a method from another component. There are multiple ways to achieve this, which are explained in more detail on this page. Here, I will demonstrate the simplest possible example of how to make ...

What is the reason behind taps in TypeScript only registering the first tap event?

One issue I am encountering is that only the first tap works when clicked, and subsequent taps result in an error message: Uncaught TypeError: Cannot read properties of undefined (reading 'classList') Here is the code I am using: https://codepen ...

What is the significance of the dollar sign prefix ($) in Vue.js?

Can you explain the significance of the dollar symbol prefix used before property names in Vue.js? For instance, consider this code snippet: this.$emit('clicked', 'demo') ...

Suggestions for enhancing or troubleshooting Typescript ts-node compilation speed?

Recently, I made the switch to TypeScript in my codebase. It consists of approximately 100k lines spread across hundreds of files. Prior to the migration, my launch time was an impressive 2 seconds when using ESLint with --fix --cache. However, after impl ...

Execute jquery commands after the function has finished

I am trying to implement the code below: $(":file").change(function () { if (this.files && this.files[0]) { console.log(this.files[0]); var reader = new FileReader(); ...

Can a custom spellchecking feature be integrated into an HTML textarea?

Question: I am wondering if it is feasible to incorporate a personalized spell checking feature into a Textarea field. Background: Currently, I am utilizing the b-form-textarea component from bootstrap-vue to present a textarea where users can input a li ...

Expanding upon passing arguments in JavaScript

function NewModel(client, collection) { this.client = client; this.collection = collection; }; NewModel.prototype = { constructor: NewModel, connectClient: function(callback) { this.client.open(callback); }, getSpecificCollection: ...