Upon submitting the form, the function executes swiftly, causing the chart.js to briefly appear before disappearing shortly after

I am working on a Javascript project that involves fetching Covid-19 data from an API source. The user inputs the name of the country they are interested in, and the data is then displayed as a graph using chart.js. I have set up an event listener on the input field to retrieve the data when the user enters the country. However, when I call the function to display the graph ( graphIt() ), it only appears for a second and then disappears. I understand that this happens because the function is called only once and executes quickly. How can I make sure the chart stays visible for as long as I want? Here is the important part of my code!

index.html

        <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.min.js"></script>
        <script src="{% static 'viewCasesChart/index.js' %}"></script>

        <div id="banner">
          <div id="banner_details">
            <h2>CoData</h2>
          </div>
        </div>    
    
       <div id="one_line">
         <div id="main_title">
           <h1>Covid-19 Data</h1>
         </div>
      
         <div id="user_query_data">
           <form id="country_form">
             <input type="text" placeholder="Country" id="country">
             <input type="submit" value="Search">
           </form>
         </div>
       </div>

       <div id="confirmed_graph">
         <canvas id="myChart" height="500" width="300"></canvas>
       </div>

index.js

    document.addEventListener('DOMContentLoaded', () => {
    //declare global variable and assign default value
    var country = "Italy";

    document.getElementById('country_form').addEventListener('submit', () => {
        var delayInMilliseconds = 100000; //
        country = document.getElementById('country').value;
        console.log("test 1", country);

        graphit();
    })
    
    async function graphit() {
        document.getElementById('myChart').style.display = "block";
        const dataset = await dataToGraph();
        
        console.log("dataset.xs", dataset.xs);
        console.log("dataset.ys", dataset.ys);

        const ctx = document.getElementById('myChart').getContext('2d');
        const myChart = new Chart(ctx, {
            type: 'line',
            data: {
                labels: dataset.xs,
                datasets: [{
                    label: `Covid 19 Confirmed cases in ${country}`,
                    data: dataset.ys,
                    backgroundColor: ['rgba(255, 99, 132, 0.2)'],
                    borderColor: ['rgba(255, 99, 132, 1)'],
                    borderWidth: 1,
                    fill: false,
                }]
            },
            options: {
                responsive: true,
                maintainAspectRatio: false,
                
                scales: {
                    yAxes: [{
                        scaleLabel: {
                            display: true,
                            labelString: 'Confirmed Cases'
                        }
                    }],
                    xAxes: [{
                        scaleLabel: {
                            display: true,
                            labelString: 'Date'
                        }
                    }],
                }     
            }
        });
    };
    
    async function dataToGraph() {
        const xs = [];
        const ys = [];
        
        var today = new Date();
        var dd = String(today.getDate()).padStart(2, '0');
        var mm = String(today.getMonth() + 1).padStart(2, '0'); //January is 0!
        var yyyy = today.getFullYear();
        today = yyyy + '-' + mm + '-' + dd;
        console.log("test 2", country);
        fetch(`https://webhooks.mongodb-stitch.com/api/client/v2.0/app/covid-19-qppza/service/REST-API/incoming_webhook/countries_summary?country=${country}&min_date=2020-04-22&max_date=${today}`)
        .then(response => response.json())
        .then(days => {
            days.forEach(day => {
                ys.push(day.confirmed);
                xs.push(day.date);
            })
        })
        
        console.log("xs", xs);
        console.log("ys", ys);
        console.log(`https://webhooks.mongodb-stitch.com/api/client/v2.0/app/covid-19-qppza/service/REST-API/incoming_webhook/countries_summary?country=${country}&min_date=2020-04-22&max_date=${today}`);
        return { xs, ys };
    };
}); // Edit: final closing brackets were missing

Answer №1

event.preventDefault() was absent during form submission:

The reason behind the absence of your chart lies in the fact that event.preventDefault() statement was missing in your form submit action. As a result, instead of executing your code, the form was sending an HTTP request (the default action).

I made some modifications to your code:

  1. included event.preventDefault() in form submission
  2. moved variable declarations outside functions to prevent repeated re-declaration
  3. removed the async feature, as fetch() is already a Promise (functions like async callbacks by default, waiting for server response)
  4. re-organized the process:
    first call dataToGraph() at form submit (using fetch() to retrieve data)
    then, after getting data from fetch()-API asynchronously, call graphit()
  5. re-assigned the data to your chart (x and y-axis data) along with top label, then update the chart using update()
  6. adapted the code for the final version of chart.js v3.5.1 for enhanced performance (v3.x does not work with v2.x):
  7. Load initial data for Italy using dataToGraph()

Execute code snippet and input a country ('Italy', 'Germany', ....)
(case-sensitive: first letter should be capital)

// define all variables here outside functions
// to avoid repetitive re-assignments
let xs = [];
let ys = [];
let dataset = {};

dataset.xs = xs;
dataset.ys = ys;

let country = "Italy";

let today = new Date();
let dd = String(today.getDate()).padStart(2, '0');
let mm = String(today.getMonth() + 1).padStart(2, '0'); //January is 0!
let yyyy = today.getFullYear();
today = yyyy + '-' + mm + '-' + dd;

const delayInMilliseconds = 100000;

const ctx = document.getElementById('myChart').getContext('2d');

const myChart = new Chart(ctx, {
    type: 'line',
    data: {
        labels: dataset.xs,
        datasets: [{
            label: `Covid 19 Confirmed cases in ${country}`,
            data: dataset.ys,
            backgroundColor: ['rgba(255, 99, 132, 0.2)'],
            borderColor: ['rgba(255, 99, 132, 1)'],
            borderWidth: 1,
            fill: false,
        }]
    },
    options: {
        responsive: true,
        maintainAspectRatio: false,
        scales: {
            yAxes: { 
                scaleLabel: {
                    display: true,
                    labelString: 'Confirmed Cases'
                }
            },
            xAxes: { 
                scaleLabel: {
                    display: true,
                    labelString: 'Date'
                }
            }
        }
    }
});

document.getElementById('country').value = country;
dataToGraph();

document.getElementById('country_form').addEventListener('submit', dataToGraph);

function dataToGraph(event) {
  if (event) event.preventDefault(); 
  
  country = document.getElementById('country').value;
  
  myChart.data.datasets[0].label =  `loading ... ${country}`;
  myChart.update();

  xs = [];
  ys = [];
  dataset = {};
  dataset.xs = xs;
  dataset.ys = ys;

  fetch(`https://webhooks.mongodb-stitch.com/api/client/v2.0/app/covid-19-qppza/service/REST-API/incoming_webhook/countries_summary?country=${country}&min_date=2020-04-22&max_date=${today}`)
    .then(response => response.json())
    .then(days => {
        days.forEach(day => {
            ys.push(day.confirmed);
            xs.push(day.date);
        });
        dataset.xs = xs;
        dataset.ys = ys;
        
        graphit();
    })
};


function graphit() {
    document.getElementById('myChart').style.display = "block";
    
    myChart.data.labels = dataset.xs;
    myChart.data.datasets[0].data = dataset.ys;
    myChart.data.datasets[0].label =  `Covid 19 Confirmed cases in ${country}`;
    
    myChart.update();
};
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

  <div id="banner">
    <div id="banner_details">
      <h2>CoData</h2>
    </div>
  </div>

 <div id="one_line">
   <div id="main_title">
     <h1>Covid-19 Data</h1>
   </div>

   <div id="user_query_data">
     <form id="country_form">
       <input type="text" placeholder="Country" id="country">
       <input type="submit" value="Search">
     </form>
   </div>
 </div>

 <div id="confirmed_graph">
   <canvas id="myChart" height="500" width="300"></canvas>
 </div>

Final Note:
Consider adding the x: { type: 'time' ... functionality to your chart for better presentation of x-axis labels (dates). Refer to this chart.js time series answer for more details.

By the way: impressive API - well done 👍

Welcome to stackoverflow

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

What is an alternative method for invoking a child function within a parent component in React?

I managed to successfully call a function in a child component from a parent component in React without using refs. However, I'm unsure if my approach is just a cheap hack. Is there a better way to accomplish this task? While I've been reading t ...

Is it possible to utilize the output of a function nested within a method in a different method?

I am currently facing a challenge with my constructor function. It is supposed to return several methods, but I'm having trouble using the value from this section of code: var info = JSON.parse(xhr.responseText); Specifically, I can't figure ou ...

Analyzing the audio frequency of a song from an mp3 file with the help of HTML5 web audio API

Currently, I am utilizing the capabilities of the HTML5 web audio API to detect when a song's average sound frequency drops below a specific threshold and create corresponding markers. Although I have successfully implemented this using AudioNodes, th ...

Executing JavaScript leads to opening Chrome instead of a web view

After receiving a form in "htmlString" and inserting it into HTML tags, including JavaScript, and loading it into a web view, the application is automatically redirecting to Chrome instead of staying within the web view itself. The form in question is a p ...

Update the radio options and link them to a particular identifier in both the database and the HTML tables

Currently, I have an AJAX request that generates a table with the following structure: | ID | Name | Radio | ======================================== | 123456 | One | Y,N | ======================================== | 78 ...

Improve the Popup to seamlessly elevate

In my project, I have implemented a pop-up dialog box that rises up from the left bottom corner as the user scrolls down the page. You can view it live at this link- However, I am facing an issue where the initial lift up of the dialog box is not smooth, ...

When using Jquery, input can be appended on the last child element when a key

I am new to JavaScript and want to enhance my page's functionality using jQuery. Here is my current HTML: <div class="input_fields_wrap"> <div><ul class="inputList"></ul></div> </div> My goal ...

Using Angular Material's MatChipList with a Dynamic FormArray: Step-by-step Guide

StackBlitz My FormArray (variants) is structured like this: this.productGroup = this.fb.group({ name: '', variants: this.fb.array([ this.fb.group({ type: '', options: '' }) ]) }) In m ...

Creating a mobile-exclusive HTML5 slider is as easy as switching to jQuery UI for other platforms

<link href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" rel="stylesheet"></link> <script src="http://code.jquery.com/jquery-1.9.1.js"></script> <script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"> ...

send a variable to a function in a random sequence

In my code, I have a function defined as follows: let showNotification = function(a,b,c,d,e,f){ console.log(a,b,c,d,e,f); } When calling this function, it is crucial to pass parameters in the correct order. For example, if I want to omit values for c, ...

Enhance your Next.js app with the SWC compiler by integrating Material UI and the swc-plugin-transform-import

I have encountered some challenges with transforming imports in Next.js using the SWC compiler. My goal is to utilize swc-plugin-transform-import instead of babel-plugin-transform-imports to simplify Material UI imports. Despite following the documented ...

What is the process of JavaScript loading external libraries?

Can anyone explain how JavaScript manages to load external libraries? Is it simply sending a GET request to the URL specified in the script tags? And where does the browser store these libraries - is it kept somewhere in the DOM? I'm concerned about ...

What is the best way to show search suggestions on Google Maps autocomplete once three characters have been entered?

While integrating google-maps into my react app, I encountered an issue with the autocomplete feature. I would like the location search to display options only when at least 3 keys are entered, but Google maps autocomplete starts showing options with jus ...

Enhance your user interface by customizing the expand icon in the React material

Currently, I am utilizing Material-table with a focus on Tree-data. You can find detailed information about this feature here: https://material-table.com/#/docs/features/tree-data. While attempting to implement the provided example, I am encountering diff ...

Utilizing div tags for creating backgrounds in HTML

I am currently in the process of developing a website and would like to incorporate particles.js as my background while overlaying the content. However, I'm facing an issue where the content is displaying on top of the page instead of behind it when I ...

Leveraging asynchronous response data within asynchronous components

Here's the structure of a parent component and a child component: export default { name : 'parentNode', mounted: function () { var that = this; if (that.$store.state.auth.isAuthenticated) { that. ...

Renaming files when uploading images using Django

Does anyone know how I can prevent duplicate filenames when uploading images to my website? Currently, when users upload photos, the system saves them in a folder called media and adds the filename to a database. However, I want to ensure that each image f ...

Tips on maintaining the content of an element within a directive template

I'm currently facing an issue with adding the ng-click directive to a button. Here's my HTML: <button class="btn">clicky</button> This is the directive I am using: angular.module('app').directive('btn', function ...

Creating a BPMN web-based designer using JavaScript

In search of a web-based UI tool to design and save bpmn workflows as XML for integration with an Angular front end. As a starting point, I need to draw bpmn shapes. Does anyone have suggestions on the best method to accomplish this using JavaScript? I&apo ...

How to manipulate iframe elements using jQuery or JavaScript

Hey there, I have a simple task at hand: I have a webpage running in an iFrame (located in the same folder on my local machine - no need to run it from a server) I am looking to use JavaScript to access elements within this iFrame from the main page. How ...