Works on freeCodeCamp but it doesn't in real project

Tell us what’s happening:
Describe your issue in detail here.

I am trying to do something similar in personal project by adding a button and a function being invoked on onclick from js file, importing this function from another js file. “Uncaught ReferenceError: monit is not defined” is all I am getting after clicking the button. How is it supposed to be done correctly?

index.js:

<!DOCTYPE html>

<html>

    <head>

        <meta charset="utf-8">

        <meta http-equiv="X-UA-Compatible" content="IE=edge">

        <title></title>

        <meta name="description" content="">

        <meta name="viewport" content="width=device-width, initial-scale=1">

        <link rel="stylesheet" href="css.css">

    </head>

    <body>

        <h1>Lets beginn!</h1>

        <button type="button" onclick=monit>monit</button>      

        <script type="module" src="js.js" async defer></script>

    </body>

</html>

js.js:

import { add, display } from './math_functions.js';

console.log(add(4,5));

alert('js.js works');

display('rr');

// function monit(){

//     display('hi, from monit');

// }

const monit=()=>{

    display('wtwrgt');

}

math_functions:

export const add = (x, y) => {

    return x + y;

  }

export const display=(txt)=>{

    alert(txt);

    return `text is ${txt}`;

}

  const uppercaseString = (string) => {

    return string.toUpperCase();

  }

 

  const lowercaseString = (string) => {

    return string.toLowerCase()

  }

I have tried many different routes to make it work, here I am trying to use display function imported from math_functions.js to js.js files.

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36 Edg/98.0.1108.43

Challenge: Reuse JavaScript Code Using import

Link to the challenge:

Please post actual code instead of pictures. Thanks.

I’m not totally sure why, but when you use script type module, you have to expose variables to the global window object: window.monit = monit. I know this is not best practice, though.

The function monit isn’t defined anywhere – in the code you posted it’s commented out, so naturally you will get an error saying that it isn’t defined. If it is defined in a different file you actually need to import the function, JavaScript can’t magically know it’s there. edit, sorry, misread code (cheers @ochsec )

Also, minor, but you use either async or defer on a script tag in HTML. But those attributes are for scripts that aren’t of type “module”. As you’ve said the type is “module” that’s already async so neither of the attributes are needed.

Don’t use the onclick attribute @6977wojtek1978, add an event listener, the function is not in the global scope (or add it to the global scope as @jonathan.roley suggests, but using an event listener is IMO and IME more sensible).

Following works fine (I’ve elided anything not relating to the code being used):

// js.js
import { display } from './math_functions.js';

const monit = () => { 
  display('wtwrgt');
}

globalThis.document.addEventListener("click", (e) => {
  if (e.target.type === "button") {
    monit();
  }
});
// math.js
export const display= (txt) => {
  alert(txt);
}
<!-- index.html -->
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>Example</title>
	<body>
		<button type="button">monit</button>
		<script src="js.js" type="module"></script>
	</body>
</html>

Note it must be run on a server over HTTP, you can’t just open the HTML file in the browser, JS modules will not work against file:// URLs. So for example, I set up the files like this:

monit
  ├ index.html
  ├ js.js
  └ math_functions.js

Then I cded into monit and (given Node is installed), ran npx servor . (ie I just ran a program that runs a server, this one happens to be a server called “servør”), server runs on localhost, so I get this:

result:

example

1 Like

I guess you can also add the function to the window object.

window.monit = () => {
  display('wtwrgt');
};

As said you really shouldn’t use inline event handlers. But if you do just know the attribute value is the code that runs.

Inline event handlers — don’t use these

the attribute value is literally the JavaScript code you want to run when the event occurs.

The function is not used as a callback, it must be invoked (). That is when onclick fires it runs the code and monit is just an identifier that contains the function definition so running that code does nothing.

<button type="button" onclick="monit()">monit</button>
1 Like

Thank you! Looks like I wasn’t running this thing on the server over HTTP, that was the main reason it wasn’t working. Thank you people, especially @DanCouper!