How to make Reusable components in Vanilla Javascript using Modules

Bahnisikha DharBahnisikha Dhar
6 min read

Have you ever faced the issue of repeatedly writing code for the same header/footer for different components of your vanilla Javascript project? Have you ever felt it would have been beneficial if you could write code once and reuse it wherever necessary? Well, trust me you are not alone in this and today in this blog, I will share an approach to how you can achieve that.

Design of the Setup

Our design looks like the below image, where the Home and About pages share the same Header. Now, we have the following files

  • index.html => consists of code for the Home page

  • about.html => consists of code for the about page

  • style.css => for styling

  • index.js => for handling logic of Home page

  • about.js => for handling logic of About Page

  • header.js => for handling logic of the Header part

Normal way to write code for header

If we followed the normal way, we would have written the same code mentioned inside the <header> tag (refer to the below code snippet) in the files index.html and about.html. Just imagine how tiring it would have been if it was a big project and complex logic were there in the header and other parts and if more than two components needed the same Header!


<body>
    <header>
        <div class="head">
            <h1>Header</h1>
            <div class="right_panel">
            <a href="index.html" class="nav-link nav-link_home">Home</a>
            <a href="about.html" class="nav-link nav-link_about">About</a>
            <button class="modal_button">Open modal</button>
            </div>
        </div>
        <div class="modal">
            <div class="modal_close">โŒ</div>
            <div class="modal_body">
                <h1>Modal</h1>
            </div>
        </div>
    </header>
    <main>
        <div class="main_body">
            <h1>Home Page</h1>
        </div>
    </main>
    <script src="index.js"></script>
    <script src="header.js"></script>
</body>

Javascript Module

Now to solve the above issue, we will create a Javascript module. Here, I am assuming that you are aware of JavaScript modules. Then again let's take a brief look at what a Javascript module is and why it is useful...

  • Reusable: A Javascript module is a file which contains codes that can be reused across different parts of a project.

  • Maintainable: It becomes easier to maintain and update code using modules, especially for large-scale projects.

  • Encapsulation: A module also allows the encapsulation of code within a file, exposing only what is necessary while keeping the rest private.

  • Export: One can export variables, functions, classes, or objects from a module using the export keyword.

  • Import: One can import variables, functions, classes, or objects from other modules using the import keyword.

Module Creation

Now that we know the benefits of a Javascript module, let's create one with the name headermodule.js .

Here in this headermodule.js file, we are creating a function named getHeaderHtml(), and returning a template literal containing the HTML structure for the <header> tag (which was previously written in index.html and about.html files). The export key suggests that this function is exported from the module, making it available for import in other JavaScript files (refer to the code below)

export function getHeaderHtml() {
    return `
    <header>
    <div class="head">
        <h1>Header</h1>
        <div class="right_panel">
        <a href="index.html" class="nav-link nav-link_home">Home</a>
        <a href="about.html" class="nav-link nav-link_about">About</a>
        <button class="modal_button">Open modal</button>
        </div>
    </div>
    <div class="modal">
        <div class="modal_close">โŒ</div>
        <div class="modal_body">
            <h1>Modal</h1>
        </div>
    </div>
</header>
    `
}

Module import

Now to get the desired result, we need to make some changes in index.html and about.html files.

  • First, remove the code with <header> tag from HTML files

  • Add a blank div with a class or id in both index.html and about.html files. Here adding an empty div with the class "m_header".

  • Add type = "module" in script tags in both index.html and about.html files


<body>
    <div class="m_header"> </div>
    <main>
        <div class="main_body">
            <h1>Home Page</h1>
        </div>
    </main>
    <script type="module" src="index.js"></script>
    <script type="module" src="header.js"></script>
</body>
  • Now import the getHeaderHtml() function in index.js and about.js file

  • Get the div with class "m_header" with document.querySelector and insert the header HTML into the DOM using innerHTML like the below code snippet

  • To get the header HTML, call the getHeaderHtml() function

import { getHeaderHtml } from './path-to-your-module';

document.querySelector(".m_header").innerHTML = getHeaderHtml();

It's all done now!!!! Now you can use this header component anywhere in your project just by calling getHeaderHtml() and inserting it into the DOM with the help of methods like innerHTML or appendChild. But wait, there is a little part which needs to be handled with a bit more care. Let's explore it below...

The correct order of script tags in the HTML file

As we are using two different script tags in the index.html file, one for index.js and one for header.js, it is important to note that the order in which the script tags are written is crucial. If the header.js script is written before index.js then the functionalities and logic like click events that open a modal on click of the Open modal button will not work. So, the correct sequence should be like the below only.

 <script type="module" src="index.js"></script>
 <script type="module" src="header.js"></script>

Now let's understand why the sequence is important.

When we include multiple <script type="module"> tags in our HTML, they are executed in the order they appear. So, if we insert <script type="module" src="header.js"></script> before <script type="module" src="index.js"></script> then header.js tries to manipulate .modal_button etc. which are not yet present in the DOM when header.js runs. This is because these elements are added dynamically by the getHeaderHtml function in index.js.

So, it is important to first insert index.js so that dynamically header element is added to the DOM by the getHeaderHtml function, and then DOM manipulation is done by header.js.

An alternate way to avoid the order of script tags

Did you find it a bit confusing to keep track of the order of script tags and want to know if there is any other way to avoid this?

Well, here we are going to discuss an approach which will help to get out of this confusion ๐Ÿ˜Š.

As in the above example, we noticed that it's important to insert header HTML into the DOM first and then after the DOM content is fully loaded, header.js should come into the picture. So, we will add the below code in our index.js and about.js files and will remove <script type="module" src="header.js"></script> from index.html and about.html files.

import { getHeaderHtml } from './path-to-your-module';

document.querySelector(".m_header").innerHTML =getHeaderHtml();

document.addEventListener('DOMContentLoaded', function() {
    const script = document.createElement('script');
    script.src = 'header.js';
    script.type = 'module';
    document.body.appendChild(script);
  });
  • The above code first inserts the header HTML into the DOM using the getHeaderHtml function

  • After the DOM content is fully loaded, it dynamically creates a script tag with a type "module" and src as header.js and then appends it to the body

This approach ensures that the header HTML is present before the JavaScript code header.js tries to manipulate it and this way one can avoid the confusion of script tag orders in HTML.

Now, as we have covered so many things and have done all the needful, we are finally able to use a single header module file wherever needed in our vanilla JavaScript project. The functionalities in header.js are working properly as well as you can see, on click of the Open modal button, Modal pops up ๐Ÿ˜Š(refer to the image below)

Hope you enjoyed the blog. Stay tuned for more such blogs ๐Ÿ˜‡

3
Subscribe to my newsletter

Read articles from Bahnisikha Dhar directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Bahnisikha Dhar
Bahnisikha Dhar