1

I'm trying to build a modular app in pure vanilla JavaScript, just for the sake of it. Importing class based modules works as expected, but I'm having some trouble with exported functions, as I get function is not defined thrown at me when I try to initialize the exported function through an onclick call.

My clickHandler.js:

export default function handleClick(target, value) {
   console.log(target, value);
}

Which gets imported in my main.js:

import handleClick from '../path/to/function/clickHandler.js';
...
<button id="my-button" onclick="handleClick(this, 1)">Test button</button>

This being a very stripped-down example of what I'm working with - why would the function be undefined at that point? In my project, the buttons are located in a obj.forEach((object) => { ... }, but I already tried to move the button with the onclick call outside of this scope, just to make sure it's not a scoping issue. Importing the function of course happens on the top of my main.js file.

Any ideas?

Pepelius
  • 1,576
  • 20
  • 34
  • 4
    Inline event listeners in HTML can't access things inside a module, since it's a *module* (they have their own private scope/namespace). Please use `addEventListener`. – kelsny Nov 05 '22 at 13:14
  • See: https://stackoverflow.com/questions/48488553/calling-javascript-function-that-is-inside-a-function-from-html and several others. – T.J. Crowder Nov 05 '22 at 13:15
  • @caTS that sounds about right. However, when I tried to bind the function call through `element.addEventListener('click', handleClick)` I couldn't get it to work. With or without parameters (which I would be needing to pass in). I've added a simple console.log to the very first line of this function to make sure it logs if it gets called, but nothing. – Pepelius Nov 05 '22 at 14:55
  • But have you used `element.addEventListener("click", (event) => handleClick(event.target, 1));`? – kelsny Nov 05 '22 at 14:58
  • @caTS Damn, I might have had a slightly incorrect syntax AND an issue with binding the event handler right after building and rendering the element it is pointed at - so introducing `setTimeout` along with your corrected syntax to add the event listener, it finally works. Thank you! Post a formal answer if you want, and I'll mark the question answered. :) – Pepelius Nov 05 '22 at 18:12

1 Answers1

2

Since modules have their own private scope or "namespace", inline event listeners in the markup can't access functions defined in the modules. You'll have to use addEventListener instead:

element.addEventListener("click", (event) => handleClick(event.target, 1));

Here in the handler we're passing the event target and a value of 1.

kelsny
  • 23,009
  • 3
  • 19
  • 48