Calling typescript function from HTML using a module system

12,633

Yes. There are 2 ways that webpack supports this

1) Output using library option. This will write the exports of the entry file to a namespace variable in global scope of your choosing

myEntryFile.ts

import {Example} from './example'
import {doSomething} from './example2'

export {
  Example,
  doSomething
}

webpack.config.js

output: {
  //... your normal output config her
  library: 'MyExposedNamespace'
}

This will now be available at window.MyExposedNamespace

window.MyExposedNamespace.doSomething()
const myExample = new window.MyExposedNamespace.Example()

For more advanced usage you can also change the scope that the namespace is applied to via libraryTarget so doesn't pollute the global scope

2) Using expose-loader

webpack.config.js

module: {
  rules: [
    { test: /example\.ts$/, 
      use: [
       { loader: 'expose-loader', options: 'Example'},
       'awesome-typescript-loader' // must transpile as file is typescript
      ]
    },
    { test: /example2\.ts$/, 
      use: [
        { loader: 'expose-loader', options: 'doSomeThing'},
        'awesome-typescript-loader'
      ]
    }
  ]
}

You must also remember to import these files in your project somewhere, otherwise webpack will ignore them. You don't have to actually use them, its just for webpack to trace dependencies. Most logical place is your entry file

myEntryFile.ts

import './example'
import './example2'

These can then be called via the global scope (in browser this is of course window)

window.doSomeThing()
const myExample = new window.Example()

This one may become trickier due to the typescript transpilation step also needing to occur before being exposed, which depending on your other config, could get more complex than the simple version above

Therefore I'd recommend the first solution as the easiest

Share:
12,633
Thomas Sparber
Author by

Thomas Sparber

Always looking for new challenges...

Updated on June 15, 2022

Comments

  • Thomas Sparber
    Thomas Sparber almost 2 years

    I would like to call a TypeScript (ultimetely JavaScript) function from HTML. The Problem is that I would also like to use a module System (systemjs, commonjs etc.) and also webpack.

    Here is an example:

    example.ts:

    export class Example {
        myFunction() {
            alert('Test');
        }
    }
    

    example2.ts:

    export function doSomething() {
        alert('Test2');
    }
    

    example.html:

    <html>
        <head>
            <script src="path/to/the/compiled/js/file.js"></script>
            <script>
                $(document).ready(function() {
                    $('#test-btn').click(function(){
                        var example = new Example(); //error1
                        example.myFunction();
                    });
                });
            </script>
        </head>
        <body>
            <button id="test-btn">Click me</button>
            <a href="javascript:doSomething()">Click me too</a> <!-- error2 -->
        </body>
    </html>
    

    The error comments indicate where the Errors happen: The exported class/function is not found because a module System is used. If I look into the compiled js files I can see that the class and function declarations are put within some module functions, so they are not accessible from HTML.

    Currently I am using a Workaround by moving the entire $(document).ready... section into a TypeScript file. But for the <a href... example I don't have any Workaround.

    So my final question: Is it actually possible to call a TypeScript function/class from HTML and using a module System?

  • Thomas Sparber
    Thomas Sparber over 6 years
    Very nice, thank you very much! That was exactly what I was looking for. Just one more question: Is it also possible that webpack Exports external libraries too? So that I can use e.g. jquery in my html file too?
  • alechill
    alechill over 6 years
    yep if you have it installed as a node module you can add add a loader for exposing it too { test: require.resolve('jquery'), use: { loader: 'expose-loader', options: 'myExposedJqueryInstance'} }