0

I have a problem in my javascript file, using Visual Studio code. I have a sample HTML file.

    <!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Page Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" type="text/css" media="screen" href="main.css" />
    <script src="main.js"></script>
</head>
<body>
    <p> hello with JSON</p>
    <button id="btn">click me!</button>
</body>
</html>

I'm trying to add an eventListener to the button I added

const btn = document.getElementById("btn");


btn.addEventListener("click", getData)


function getData(){
    fetch('https://jsonplaceholder.typicode.com/users')
    .then((res) => { return res.json() })
    .then((data) => { 
        console.log(data);
    });
}

Why is this issue happening?

Ating
  • 2,540
  • 1
  • 11
  • 39
  • 1
    try adding your script at the bottom of the body – Zohir Salak Oct 21 '18 at 10:45
  • this works.. but i still don't no why it won't work with external file? – Ating Oct 21 '18 at 10:48
  • Maybe because you're prematurely adding an `eventListener` to a node that does not yet exist in the DOM. Run the JS _after_ you've got the node in the DOM. – Klemen Tusar Oct 21 '18 at 10:49
  • @baileyhaldwin it is still an external file, the problem is that the document load from top to bottom, therefore the JS will load and run first before the document finish loading, and by default asking for something that isn't there yet, will result in null – Zohir Salak Oct 21 '18 at 11:02

4 Answers4

2

If you don't wanna refactor to much of your code add the defer keyword to your script tag like this:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Page Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" type="text/css" media="screen" href="main.css" />
    <script src="main.js" defer></script>
</head>
<body>
    <p> hello with JSON</p>
    <button id="btn">click me!</button>
</body>
</html>
Klemen Tusar
  • 7,916
  • 4
  • 26
  • 26
1

Move your script reference to the end of you body section.

<body>
    <p> hello with JSON</p>
    <button id="btn">click me!</button>
    <script src="main.js"></script>
</body>

That way, your code will run after the button HTML is already rendered and ready.

Shai Aharoni
  • 1,828
  • 11
  • 24
  • in your code The command: 'btn = document.getElementById("btn");' is executed BEFORE the tag is rendered therefore it is not found and btn is set to null. HTML is executed top to bottom , so code that appears first will also execute first – Shai Aharoni Oct 21 '18 at 10:50
1

You need to wait until the document is fully loaded before making DOM manipulations (in your case, the binding of the listener to the button element). If you are executing the script before the element is available, it is not found and the listener is not added.

  • One way would be to put the script part (the external file or the scripts directly inside of the HTML file) to the bottom of the page – or at least after the <button> declaration.
  • Another way would be to have it at the top but within the script part, you'll need to wait for the DOM to be loaded. For that, see here: https://stackoverflow.com/a/800010/3233827
ssc-hrep3
  • 10,806
  • 4
  • 35
  • 77
1

Move your script tag to the end of the body tag and not include it in the head tag.

Generally it is good practice to add the script tag after the html portion of the code is written.

In your case the browser loads and executes the script before the main tag is executed causing your issue.

harikris
  • 63
  • 6