Search code examples
javascriptdomshadow

access to shadow dom properties


so here is my script code

class Pop extends HTMLElement {
  constructor() {
    super();
  }
 connectedCallback() {
 let currDoc = document.currentScript.ownerDocument;
  let template = currDoc.querySelector('#pop-up');
  let tmplNode = document.importNode(template.content, true);

  let shadowRoot = this.createShadowRoot();
  shadowRoot.appendChild(tmplNode);
  shadowRoot.querySelector("#content").innerHTML = this.innerHTML;
 }
}
 window.customElements.define("pop-up", Pop);

and here is my template

<template id="pop-up">
    <style>
     * {
     padding: 0;
      margin: 0;
    }

.btn {
  //styling
}

.btn:hover {
  //styling
}

#box{
    //styling
    display: none;
}

#box h1{
    //styling
}

 </style>

<div id="box">
    <h1> Your Shopping Cart</h1>
    <text id="content"> </text>

    <button class="btn" onclick="close()"> Close </button>
</div>
</template>

and in my index file i have this

<button class="btn" onclick="pop()">Show Pop</button>
<pop-up id="pop"> pop-up box</pop-up>

<script>
    function pop(){
        document.getElementById("pop").style.display = "block";
    }
</script>

I am trying to do a pop-up box. And when i click on the "Show Pop" button i want to change the display property from style to "block" from "none". But for some reason it doesn't work. Im new to this shadow dom elemets and i can't really figure it out.


Solution

  • It is hard to explain everything in this answer, but the following code will give you an overview of how the solution might look like.

    MDN, as usual, has the perfect intro for web components and shadow doms here

     class Pop extends HTMLElement {
          constructor() {
    
            // Always call super first in constructor
            super();
            let template = document.getElementById('pop-up');
            let templateContent = template.content;
    
            // Create a shadow root
            const shadowRoot = this.attachShadow({ mode: 'open' })
              .appendChild(templateContent.cloneNode(true));
             
            // attach close listener
            this.shadowRoot.querySelector('.btn').addEventListener('click', this.close.bind(this));
          }
         
          //  close pop-up
          close() {
            this.style.display = 'none';
          }
    
          //  open pop-up
          open() {
            this.style.display = 'block';
          }
        }
        window.customElements.define("pop-up", Pop);
        
         function pop() {
          // notice we are using the open method here 
          document.getElementById("pop").open();
        }
      <template id="pop-up">
        <style>
          :host {
            display: none;
          }
    
          * {
            padding: 0;
            margin: 0;
          }
    
          .btn {
            //styling
          }
    
          .btn:hover {
            //styling
          }
    
          #box {
            //styling
            display: none;
          }
    
          #box h1 {
            //styling
          }
        </style>
    
        <div id="box">
          <h1> Your Shopping Cart</h1>
          <!-- Notice we are using slots -->
          <slot> </slot>
    
          <button class="btn"> Close </button>
        </div>
      </template>
      
       <button class="btn" onclick="pop()">Show Pop</button>
      <pop-up id="pop"> pop-up box </pop-up>