Pradeep Kumar K
Pradeep Kumar K

Reputation: 21

Not able use Bootstrap within Shadow Root of Custom Elements

I am creating a web component using the plain javascript and using Bootstrap 5 for styling. The bootstrap styling works fine but the eventlisteners of bootstrap dropdown is not working.

I have encapsulated the bootstrap javascript content inside script tag and placed inside the shadowroot.

I am new to web components and shadow root. I am not sure whether using bootstrap inside the shadow root is good approach or not.

Thanks in advance!

Please find below code for your reference.

web-component.js

const template = document.createElement('template');

template.innerHTML = `
    <style>
        @import url("https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css");
    </style>
    <div class="container-fluid">
        <div class="dropdown">
            <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton1" data-bs-toggle="dropdown" aria-expanded="false">
                Dropdown button
            </button>
            <ul class="dropdown-menu" aria-labelledby="dropdownMenuButton1">
                <li><a class="dropdown-item" href="#">Action</a></li>
                <li><a class="dropdown-item" href="#">Another action</a></li>
                <li><a class="dropdown-item" href="#">Something else here</a></li>
            </ul>
        </div>
    </div>
`;
class WebComponent extends HTMLElement {
    constructor(){
        super();
        this.attachShadow({ mode: 'open'});
        this.shadowRoot.appendChild(template.content.cloneNode(true));

        const scriptElement = document.createElement('script');
        scriptElement.src = "https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js";
        scriptElement.integrity = "sha384-b5kHyXgcpbZJO/tY9Ul7kGkf1S0CWuKcCD38l8YkeH8z8QjE0GmW1gYU5S9FOnJ0";
        scriptElement.crossorigin = "anonymous";
        this.shadowRoot.appendChild(scriptElement);
    }
}

window.customElements.define('b-comp', WebComponent);

sample.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Dummy Web Component</title>
</head>

<body>
    <b-comp></b-comp>

    <script src="web-component.js"></script>
</body>

</html>

In the output the button is created with proper bootstrap style but nothing happens when it is clicked.

Upvotes: 0

Views: 4492

Answers (1)

Harshal Patil
Harshal Patil

Reputation: 20980

TLDR; It is not possible with what you are trying to do.

The bootstrap won't be able to respond to events happening within the Shadow DOM. There are solutions available in bits and pieces.

For shared CSS across multiple instances of same component with Shadow DOM, you can consider using Constructible Stylesheets.

For ability to use bootstrap's JavaScript, you have to rely on Light DOM as suggested in this answer. But that will not work when you have component composition. Imagine, using your dropdown in another web-component which has its own Shadow DOM and thus multiple levels of nested Shadow DOM. You cannot guarantee that your light DOM would always not scoped to other component's shadow DOM.

Alternately, you can consider building component without using shadow DOM.

Upvotes: 3

Related Questions