0

I want to make sure my javascript work only after all content is loaded. So, I put my code inside a load event listener. If I create a function inside that event, and try to call it in a onclick event, in a button, I got a error saying my function is not defined.

Error: Uncaught ReferenceError: sayHello is not defined at HTMLButtonElement.onclick

If I remove the function from the load event, it works. Why this happens?

index.html

<html>
<head>
    <script src="/js/index.js"></script>
</head>
<body>

    <button onclick="sayHello()">Say Hello</button>

</body>
</html>

index.js

window.addEventListener("load", async () => {

    function sayHello(){
        alert("Hello!");
    }

});
0neX
  • 3
  • 5
  • Possible duplicate of [Function is not defined - uncaught referenceerror](https://stackoverflow.com/questions/5067887/function-is-not-defined-uncaught-referenceerror) – Sebastian Simon Jul 17 '19 at 23:23
  • Either don’t declare functions inside the `load` listener or bind the `click` event listener inside it, too. Consider using `DOMContentLoaded` instead of `load`, [avoid](https://stackoverflow.com/q/11737873/4642212) using attributes like `onclick`. Why is your listener an `async` function? – Sebastian Simon Jul 17 '19 at 23:26
  • @SebastianSimon, Thanks for the answer! I tried `DOMContentLoaded`, but I got the same error. My listener is an `async` because some await imports I'll use. Why is a bad idea use `onclick`? – 0neX Jul 17 '19 at 23:33
  • The solution wasn’t `DOMContentLoaded`; it was the first sentence. Inline event handlers like `onclick` or `oninput` are [not recommended](https://stackoverflow.com/q/11737873/4642212). They are an [obsolete, hard-to-maintain and unintuitive](https://stackoverflow.com/a/43459991/4642212) way of registering events. Always [use `addEventListener`](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Inline_event_handlers_%E2%80%94_don't_use_these) instead. – Sebastian Simon Jul 17 '19 at 23:35
  • Thanks for the help! – 0neX Jul 17 '19 at 23:39

1 Answers1

1

Try it like this. in this model we do not assign the click function until the DOMContentLoaded event is triggered.

document.addEventListener('DOMContentLoaded', () => {
  document.querySelector('.sayHello').addEventListener('click', () => console.log('Hi'))
});
<html>
<head>
    <script src="/js/index.js"></script>
</head>
<body>
    <button class="sayHello">Say Hello</button>
</body>
</html>
Bibberty
  • 4,670
  • 2
  • 8
  • 23