Tips for successfully sending a nested function to an HTML button and dropdown menu

I'm working on two main functions - getChart() and fetchData(). The goal is to retrieve chart data and x/y axes information from a database. Within the getChart function, I'd like to incorporate a dropdown menu for displaying different types of charts when selected. Anyone able to provide some assistance? Thanks!

<body>
<div class="chartMenu">
    <p>Loan Applications Accepted</p>
    <div class="chartCard">
        <div class="chartBox">
            <canvas id="myChart"></canvas>
            
            <button onclick="(new getChart()).back();"> GO BACK </button>
            <select onchange="(new start()).changeChart();">
                <optgroup label="Select Chart"></optgroup>
                <option value="bar">Bar</option>
                <option value="pie">Pie</option>
                <option value="line">Line</option>
                 <option value="doughnut">Doughnut</option>
              </select>

function fetchData(url) { $.ajax({ url: url, type: "GET",

                    success: function (data) {
                        coordinates = [];
                     
                        Array.from(data).forEach(element => {
                            coordinates.push({ x: element.x_axis, y: element.y_axis })
                            

                        });


                        getChart();

                    },

                    error: function (error) {
                        console.log(`Error ${error}`);
                    }
                });






            };

function getChart() {

   
      var data = {

        datasets: [{
          label: 'No of Loan Applications',
          data: coordinates,

          backgroundColor: [
            'rgba(193, 32, 32, 0.58)',
            'rgba(75, 192, 192, 0.58)',
            'rgba(255, 159, 64, 0.58)',
            'rgba(153, 167, 64, 0.58)',
            'rgba(153, 102, 255, 0.58)',
         
          ],
          borderColor: [
            'rgba(255, 99, 132, 0.2)',
            'rgba(75, 192, 192, 0.2)',
            'rgba(255, 159, 64, 1)',
           
          ],
          borderWidth: 1
        }]

      };

  
      var config = {
        type: 'bar',
        data,
        options: {

          scales: {
            y: {
              
            },


          },

        }


      };


     
      var ctx = document.getElementById('myChart');

      let myChart = new Chart(
        ctx,
        config

      );

 

      this.back = function () {
          if (myChart != null) {
              myChart.destroy();
          }
          fetchData('http://localhost:8080/jsonGet?year=1')
          myChart.data.datasets[0].data = coordinates;
          myChart.update();
      };


      function clickHandler(click) {


        const points = myChart.getElementsAtEventForMode(click, 'nearest', { intersect: true }, true);
        
        if (points.length) {
          const firstPoint = points[0];
          

          if (firstPoint.element.$context.raw.x == "2020") {

            fetchData('http://localhost:8080/jsonGet?year=2020')
            myChart.data.datasets[0].data = coordinates;
            myChart.update();



          }

          else if (firstPoint.element.$context.raw.x == "2021") {

            fetchData('http://localhost:8080/jsonGet?year=2021')
            myChart.data.datasets[0].data = coordinates;
            myChart.update();

          }

          else if (firstPoint.element.$context.raw.x == "2022") {

            fetchData('http://localhost:8080/jsonGet?year=2022')
            myChart.data.datasets[0].data = coordinates;
            myChart.update();

          }



          else {
            console.log("Wrong input");
          }

        }
      };
      ctx.onclick = clickHandler;

      function changeChart(chartType) {
        console.log(chartType);
        console.log(chartType.value);
      }

      function start() {
        getChart();
        clickHandler(click);
        changeChart(chartType)
      }

      start();

    };

    $(document).ready(fetchData(url));

Answer №1

What's going on here is quite interesting.

When you invoke getChart(), it triggers a call to start(), and within start() there's another call to getChart()!! This leads to an infinite recursion, but fortunately, the recursion stops after the second invocation of getChart() because the chart is not being destroyed.

One way to solve this issue is by separating each function from getChart and eliminating the recursive call.

Next, update the select element as follows:

<select id="types">

In your JavaScript code, add the following snippet to handle the change event:

$(function () {
    // On changing the type of the chart
    $(document).on("change", "#types", function () {
        let type = $('#types').val();
        changeChart(type);
    });
})

To switch the type of chart, you must first destroy the existing chart. Then, recreate the chart with the selected type.

function changeChart(newType) {
    if (chart) {
        chart.destroy();
    }
    myChart = new Chart("myChart", {
        type: newType,
        .
        .
        .
    }
}

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

Which is better for testing in Cypress: classes or functions?

When it comes to testing in Cypress, which approach do you believe is more efficient? Functions: 'support/pages/login.js' export const login = (username, password) => { cy.get('#username').type(username); cy.get(& ...

Vue parent component not receiving events properly

Referring to these sources: Forum Post Stack Overflow Question In my project, I am utilizing: CodeSandbox Example The setup involves the parent component listening for events emitted by a child component: mounted() { this.$on("edit-category& ...

Angular setPristine function is not functioning properly

I am looking to achieve a simple task - cleaning the $scope.user fields without encountering errors. if ($scope.contactForm.$valid) { $scope.user = {}; $scope.contactForm.$setPristine(); } However, I'm still experiencing v ...

Is there a quicker alternative to the 500ms delay caused by utilizing Display:none?

My div is packed with content, including a chart from amCharts and multiple sliders from noUiSlider. It also features various AngularJS functionalities. To hide the page quickly, I use $('#container').addClass('hidden'), where the rule ...

Utilizing Vue.js: accessing a global value within a template string

I am working on a simple Vue.js application with the following structure: index.html (only the <body> for brevity) <div id="root"></div> main.js var settings = { title: 'My App', } new Vue({ el: '#root', tem ...

Learn how to customize the appearance of tooltips by using the jQuery qTip Plugin to split the 'title' attribute and apply unique styles

Currently experimenting with the qTip jQuery plugin showcased at this link. Managed to get the code functioning based on the demo, but aiming to "explode" the content from the TITLE attribute. The objective is for the first item in the array to serve as t ...

The tooltip is obscured by the table row

I'm having trouble with a simple CSS fix and can't seem to figure out why. The z-index and overflow visibility properties are not working as expected. I just need 'In Progress' to be displayed above everything else. Some things I' ...

I am attempting to swap values within table cells using AngularJS. Would it be recommended to utilize ngBind or ngModel, or is there another approach that would

How can I make a table cell clickable in AngularJS to switch the contents from one cell to another, creating a basic chess game? I want to use angular.element to access the clicked elements and set the second clicked square equal to the first clicked using ...

Encountering redundant links during the scraping process

I'm currently working on extracting "a" tags with the class name "featured" from a specific website . Although the code I've written seems to be error-free, it unfortunately duplicates the links. How can I resolve this issue and avoid the duplica ...

Move the footer to the bottom of the content

I'm struggling to position my footer directly after the last div on my page, as it's appearing lower than I'd like. Can anyone assist with this issue? Here is the code snippet: <div id="container"> <div id="header"> ...

Modifying the jquery cookie's value

As soon as a user lands on my site, a persistent cookie (x1st) is set with a unique value (such as 'hdflashfafafxx233ddd'). This particular cookie is utilized for tracking purposes. However, if the user chooses to opt out of tracking cookies, I ...

What is the process of invoking a secondary "external" function with Nodejs, Expressjs, and bluebird?

Struggling with creating a nodejs application, a new area for me. I've managed to work with Promises and fetch data from a database. Take a look at the code below: myModel.js var express = require('express'); var app = express(); var Promi ...

Manage multiple sessions at the same time

In a specific scenario, we face the need to manage multiple sessions similar to Google Accounts. Users should be able to add different accounts in separate tabs, each with its own unique content. For example, user1 may be logged in on Tab1 while user2 is l ...

Learn the process of updating a nested document within an array in MongoDB

I have a data structure as shown below: { "name":"xxxxxx", "list":[ { "listname":"XXXXX1", "card":[ { "title":"xxxxxx", "descip":"xxxxxxx ...

Updating select option values without reloading the page using a modalHere is an efficient method for updating

Is there a way we can update the select tag option values without having to reload the page after submitting data in the bootstrap modal? Currently, we are facing an issue where the submitted values do not show up in the option tag until the page is reload ...

Scroll the div that is dynamically filled without affecting the scrolling of the main page

My current struggle involves using iScroll in my web project. The goal is to populate a list with articles and slide in a div over the list to display the selected article. While the basic functionality is in place, I face an issue where scrolling through ...

Failed to load component due to error: Module "jquery" not found

I am attempting to dynamically load the jquery library on my webpart .ts file. This piece of code successfully loads jquery: import { SPComponentLoader } from '@microsoft/sp-loader'; import * as $ from 'jquery'; export default class ...

When using jQuery, the .change() function will only be triggered after the user clicks a button or

Looking for assistance with an unusual issue in my JavaScript/jQuery code. The jQuery .change() function on a simple text input element only triggers when I click somewhere on the page, open the Chrome console, or press a key on the keyboard. It doesn&apo ...

Switch between a list of labels dynamically with checkboxes in React

I'm currently working on a React component that displays an array of cars. I want to show a list of labels with the names of all diesel cars by default, and then have a checkbox that, when clicked, toggles to show all cars. interface ICars { name ...