9

I tried to create a shadow DOM for encapsulating the content Script elements and then apply Bootstrap styles and also make Bootstrap Modal work inside a shadow Dom so it can encapsulate itself from the Webpage styles and Scripts. It is successful in displaying the content but Bootstrap js scripts don't work.

I tried injecting all the Styles and Script files inside the Shadow DOM. Bootstrap Styles work, Bootstrap Scripts don't work

$(#id) //the usual way to access a id using jQuery

parentofShadowtree.shadowRoot.querySelector('#id') //to select a element inside shadow DOM

I think the error is because the Bootstrap scripts are not able to access the elements as they usually would.

I believe since the way of accessing elements has changed, these script files doesn't work.

Am I right? Is there a way to overcome this problem

vba
  • 526
  • 8
  • 20
  • 1
    You're right. Don't use Shadow DOM with Boostrap scripts. To overcome this problem maybe you could overload the querySelector method, but I haven't tried. – Supersharp Jul 13 '19 at 20:53
  • @Supersharp I guess that is super hard for me and decided to go without shadow dom. – vba Jul 15 '19 at 04:31

1 Answers1

9

If you still want to use Shadow DOM the workaround is to put the Bootstrap UI elements in the light DOM and then insert then with in the Shadow DOM.

customElements.define( 'c-e', class extends HTMLElement {
    constructor() {
        super()
        this.attachShadow( { mode: 'open' } )
            .innerHTML = `
                <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
                <button class="btn btn-primary">CSS Only</button>
                <slot name="dropdown"></slot>`
    }
    connectedCallback() {
        this.innerHTML = `<section slot="dropdown">        
                <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                    Dropdown button
                </button>
                <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
                    <a class="dropdown-item" href="#">Action</a>
                    <a class="dropdown-item" href="#">Another action</a>
                    <a class="dropdown-item" href="#">Something else here</a>
                </div>
            </section>`
    }
} )
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<c-e></c-e>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
Supersharp
  • 29,002
  • 9
  • 92
  • 134
  • 1
    This is what I want. Awesome! Will go through the solution – vba Jul 16 '19 at 06:42
  • I'm having a similar issue - https://stackoverflow.com/questions/60795202/making-javascript-script-available-to-shadow-dom?noredirect=1#comment107562217_60795202. Can you please help? – methuselah Mar 22 '20 at 07:49
  • 1
    @methuselah sorry I don't know Angular well but I suppose you should put your elements in the light dom (as describe above) – Supersharp Mar 22 '20 at 18:48
  • so, is it loading bootstrap's styles twice? – roadev Feb 25 '21 at 16:47
  • nevermind, I just tested it and it only loads once – roadev Feb 25 '21 at 16:59
  • I don't think this works when you use Bootstrap components (that rely on JavaScript) inside a custom element, inside a custom element. The light DOM of the inner custom element is still inside the outer custom element's shadow DOM. – Rudey Aug 16 '22 at 20:29