2

Here is what I am trying to do.

I created an HTML page with a table. I have all tags defined except for the body tags.

I have a javascript that fetches data from the web in JSON format, parses it, and writes elements to table body with tags using innerHTML. It works perfectly if you let it run. But if I put this "fetch" code in a function and execute this function from "onclick" of "submit" button, the logic stops working. I placed an alert at the beginning of the function and I can see it, but the fetch part is not working. I tried to use a regular function and async (await). Neither is working.

Here is my code (starting at the form). Please let me know what I'm doing wrong.

Thanks.


<form enctype="multipart/form-data" action="" method="post">
    <button type="submit" name="submit" id="Submit" value="click" onClick = getEarnings()>Click </button>
</form>

<table>
  <thead>
    <tr">
        <th>Reported Date</th>
        <th>Reported EPS</th>
        <th>Estimated EPS</th>
        <th>Surprise</th>
    </tr>
  </thead>
  <tbody id="myData"><tbody>
</table>

<script>
/* function getEarnings() { */
    fetch('https://www.alphavantage.co/query?function=EARNINGS&symbol=IBM&apikey=demo')
      .then(res => res.text())
      .then((out) =>
         {
            alert("I am here"); // I can't see it if from function
            let jsonData = JSON.parse(out);
            for (let i = 0; i < jsonData.quarterlyEarnings.length; i++)
             {
                let earnings = jsonData.quarterlyEarnings[i];
                document.getElementById("myData").innerHTML +=
                "<tr><td>" + earnings.reportedDate + "</td>" +
                "<td align='right'>" + earnings.reportedEPS + "</td>" +
                "<td align='right'>" + earnings.estimatedEPS + "</td>" +
                "<td align='right'>" + earnings.surprise + "</td></tr>";
             };
         })
      .catch(err => console.error(err));
/* } */
</script>
Mario Petrovic
  • 7,500
  • 14
  • 42
  • 62
Jake
  • 55
  • 5

3 Answers3

3

You don't need a form to fetch data. My suggestion:

getData.onclick = () => {
  fetch('https://www.alphavantage.co/query?function=EARNINGS&symbol=IBM&apikey=demo')
    .then(res => res.text())
    .then((out) => {
      let jsonData = JSON.parse(out);
      for (let i = 0; i < jsonData.quarterlyEarnings.length; i++) {
        let earnings = jsonData.quarterlyEarnings[i];
        myData.innerHTML +=
          "<tr><td>" + earnings.reportedDate + "</td>" +
          "<td align='right'>" + earnings.reportedEPS + "</td>" +
          "<td align='right'>" + earnings.estimatedEPS + "</td>" +
          "<td align='right'>" + earnings.surprise + "</td></tr>";
      };
    })
    .catch(err => console.error(err));
}
<button type="button" id="getData">Get data</button>
<table>
  <thead>
    <tr>
      <th>Reported Date</th>
      <th>Reported EPS</th>
      <th>Estimated EPS</th>
      <th>Surprise</th>
    </tr>
  </thead>
  <tbody id="myData">
    <tbody>
</table>
AbsoluteBeginner
  • 2,160
  • 3
  • 11
  • 21
2

when you click the button in Tag, your page will refresh and you should avoid this like this

const getEarnings = (e) => {
// prevent browser from refreshing
e.preventDefault()

fetch()

}
hamidreza nikoonia
  • 2,007
  • 20
  • 28
1

A few things:

  1. Use "onclick" instead of "onClick" (see note at bottom)
  2. Set the call on your HTML attribute inside quotes like: onClick="getEarnings();"
  3. Stop the event propagation since your button is a submit type and will force a page reload. This can be done a couple ways:
    • You can make the button type "button" instead of "submit" since the latter forces a page reload.
    • You can accept the event into the function and then stop the event from continuing like:
function getEarnings (e) {
    // This will stop a submit button from reloading the page
    e.preventDefault();
    // Logic here
}

Ideally, you would instead have this logic entirely in a script where your button has a unique id you can target and set an event listener on it when the DOM has loaded. That way you can move all of this to a separate file and keep the presentation and logic separate. Off the top of my head, it would be something like this:

window.addEventListener('DOMContentLoaded', function () {
    const submit = document.getElementById('Submit');
    submit.addEventListener('click', function (e) {
       e.preventDefault();
       // run logic
    });
});

NOTES:

  • Regarding #1, its just a good habit to use lowercase because in JS onClick won't work the same way: onclick or onClick?
  • If you require legacy browser support, you should be aware of some of the oddities with click events: addEventListener vs onclick
Jeremy Harris
  • 24,318
  • 13
  • 79
  • 133