How to call a function declared in a javascript module (type=module) from an html page

Viewed 4559

I am struggling to use javascript modules...

I have an html file and a JS module. I have a function defined in the javascript file and I would like to call that function from my HTML page. This is my code

index.html

<html>
<head>
  <script type="module" src="app.js"></script>
</head>
<body>
  <button onclick="greetFromHtml();">greetFromHtml</button>
  <button onclick="greetFromModule()"> greetFromModule</button>
  <script type="text/javascript">
    function greetFromHtml(){
      alert('Hello');
    }
  </script>
</body>
</html>

app.js

function greet(){
  alert('Hello');
}

The greetFromHtml button works fine. When I click the greetFromModule button I get this error: hello is not defined at HTMLButtonElement.onclick

If I remove type="module" from the header, it all works fine, however I need to use modules for some other reasons, so this is not a good solution here.

I have seen several posts saying I need to import/export or use window but I am not sure what to do. Can anyone provide an answer please? Ideally the simplest way to achieve it

See below the reference to some question I have reviewed:

function in my javascript module is not defined

Call functions in a JavaScript from an HTML

How to use code from script with type=module [duplicate]

ES6 Modules: Undefined onclick function after import

EDIT I have tried the following but still getting the same error enter image description here enter image description here enter image description here

EDIT 2 The code in the answer is working. I was just trying to run in locally but I understood you need a server, so if you see the same error, upload the site to server or use a local server.

1 Answers

First of all you have to explicitly export you function:

export function greet() {
  alert("Hello from module");
}

Secondly, a module has it's own scope (this is the whole point of modules) thus you need to add the function to the global scope. So, to do it you have to run a script which imports the function and adds it to the window object:

<script type="module">
  import { greet } from "./app.js";
  window.greetFromModule = greet;
</script>

Now you don't need this part <script type="module" src="app.js"></script>

Alternatively you can create an empty obj and add your modules stuff to it, this is what it would look like:

<html>
  <head></head>
  <body>
    <button onclick="greetFromHtml();">greetFromHtml</button>
    <button onclick="module.greet()">greetFromModule</button>
    <script type="text/javascript">
      function greetFromHtml() {
        alert("Hello");
      }
      const module = {};
    </script>
    <script type="module">
      import { greet } from "./app.js";
      module.greet = greet;
    </script>
  </body>
</html>
Related