Search code examples
typescriptcustom-element

Define, Importing and Using Custom Element in TypeScript and HTML


I am trying to define a custom element and use it in the HTML template, but it doesn't show up, nothing gets logged from the console. It seems the element doesn't get defined this way.

What am I doing wrong? I am using webpack and TypeScript.

I have defined a class that extends a HTML element in top-bar.ts

export class TopBar extends HTMLElement {

    shadowDOM : ShadowRoot;

    constructor() {
        super();
        console.log('from constructor');
        this.shadowDOM = this.attachShadow({mode:"open"});
    }

    connectedCallback() : void {
        this.render();
    }

    render() : void {
        this.innerHTML = `

        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
        <style>
            .top-bar {
                box-shadow: 0px 2px 10px 6px #ccc;
                height: 40px;
            }
            
            .top-bar h5 {
                margin-bottom: 0;
                color: #273C75;
            }
            
            .top-bar img {
                display: block;
                width: 36px;
                height: 36px;
                margin-right: 0.5rem;
            }
        </style>
        <nav class="top-bar d-flex justify-content-center align-items-center">
            <img src="img/Beep-Signal.png" alt="">
            <h5>LoRa Dashboard</h5>
        </nav>
        `
    }

}

customElements.define("top-bar", TopBar);

and in index.ts, I import the TopBar.

import * as TopBar from './components/top-bar'

and in index.html, I put the top-bar element

<!DOCTYPE html>
<html>
  <head>
    <title>LoRa Dashboard</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
  </head>
  <body>
    <script src="bundle.js"></script>
    <top-bar></top-bar>
  </body>
</html>

Solution

  • So after a while, I finally found that top-bar.ts doesn't seem to get included in the bundle.

    It seems like top-bar doesn't get included although I have imported it in index.ts, my suspect is because that nothing from top-bar.ts is used anywhere in index.ts, only in HTML (when testing). That's why the custom element never gets defined.

    So I added a dummy function in top-bar.ts and called it in index.ts only to get it included. This works for my project for now, and I'm new to TypeScript and JavaScript, but I'm sure that there is a better workaround instead of calling a dummy function just to get it included.