skip to Main Content

I’ve created a custom element and defined it in html as follows:
`

<header>
    <custom-navbar links="[{title:'home'},{title:'About'}]" class="bg-purple">
        <h1 slot="logo">
            Amazon
        </h1>
    
        <navbar  slot="link" class="navbar-wrapper">
            <ul  class="link-container">
               
            </ul>
        </navbar>
    </custom-navbar>
</header>

`

An I’ve defined my custom element as follows:

class CustomNavbar extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: "open" });
    this.shadowRoot.innerHTML = `
    
        <style>
           :host(.bg-purple){
                display:flex;
                width:100%;
                background-color:purple !important;
           
            }

            .container{
                display:flex;
                flex-direction:row;
                margin:1rem;
                align-items:center;
            
            }
   
        </style>

        <div class='container'>
                <div>
                    <slot name="logo"></slot>
                </div>
                <slot name='link'></slot>
        </div>
    
    
    `;
    }

     connectedCallback() {
       this._links = this.getAttribute("links");
   
        }
    }

    customElements.define("custom-navbar", CustomNavbar);


I am looking for getting the links attribute defined in light DOM in shadow DOM and add the link to ul element? I’ve also use :document.querySelector("custom-navbar").querySelector("ul") inside of connectedCallback(), But it didn’t work correctly.

2

Answers


  1. Try this code, it creates and populates a list of links dynamically within the shadow DOM by using the links attribute provided in the custom element’s HTML.

    class CustomNavbar extends HTMLElement {
      constructor() {
        super();
        this.attachShadow({ mode: "open" });
        this.shadowRoot.innerHTML = `
          <style>:host(.bg-purple){display:flex;width:100%;background-color:purple!important;}.container{display:flex;flex-direction:row;margin:1rem;align-items:center;}</style>
          <div class='container'><div><slot name="logo"></slot></div><slot name='link'></slot></div>
        `;
      }
    
      connectedCallback() {
        const links = JSON.parse(this.getAttribute("links") || '[]');
        const ulElement = this.shadowRoot.querySelector("ul.link-container");
        
        links.forEach(linkInfo => {
          const liElement = document.createElement("li");
          liElement.textContent = linkInfo.title;
          ulElement.appendChild(liElement);
        });
      }
    }
    
    customElements.define("custom-navbar", CustomNavbar);
    

    Hope it works 🙂

    Login or Signup to reply.
  2. The connectedCallback fires on the opening tag; so there is no parsed lightDOM yet at this stage
    (unless the CE is defined after DOM parsing)

    So you either:

    • use setTimeout inside the connectedCallback to postpone quering for your <ul> tag in lightDOM

    • add a insertLI method on you component that checks/waits for the <ul> to exist

    The setTimeout is totally valid unless you have a very LARGE lightDOM (like > 750 DOM nodes) then add HTML-parsed-element code

    Note:

    super();
    this.attachShadow({ mode: "open" });
    this.shadowRoot.innerHTML = `...`
    

    can be chained to:

    super() // sets AND returns 'this' scope
        .attachShadow({ mode: "open" }) // sets AND returns this.shadowRoot
        .innerHTML = `...`
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search