Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

110
Visualizações
why it doesn't loop through the loop (JavaScript, Class, ShadowDOM, HTML Template tag)

      class Product extends HTMLElement {
        connectedCallback() {
          let products = [
            { name: "carrot", price: "$ 6.99" },
            { name: "blueberry", price: "$ 6.99" }
          ];

          let pro = document.querySelector("#product_item").content;
          let copyHTML = document.importNode(pro, true);

          for (let product of products) {
            copyHTML.querySelector(".cerealName").textContent = product.name;
            this.attachShadow({ mode: "open" });
            this.shadowRoot.append(copyHTML.cloneNode(true));
          }
        }
      }
      customElements.define("product-item", Product);
    <main>
      <product-item></product-item>
      <product-item></product-item>
    </main>

    <template id="product_item">
      <li class="cereal">
        <p class="cerealName" style="font-size: 3rem"></p>
      </li>
    </template>

I expected the result to be a

carrot blueberry

But the result came with

carrot carrot

I can't seem to run the loop, can you tell me why?

almost 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

You only need to call attachShadow once - after that it generates an error:

Failed to execute 'attachShadow' on 'Element': Shadow root cannot be created on a host which already hosts a shadow tree.

You also only need one <product-item> element.

      class Product extends HTMLElement {
        connectedCallback() {
          let products = [
            { name: "carrot", price: "$ 6.99" },
            { name: "blueberry", price: "$ 6.99" }
          ];

          let pro = document.querySelector("#product_item").content;
          let copyHTML = document.importNode(pro, true);
          this.attachShadow({ mode: "open" });
          for (let product of products) {
            copyHTML.querySelector(".cerealName").textContent = product.name;
            this.shadowRoot.append(copyHTML.cloneNode(true));
          }
        }
      }
      customElements.define("product-item", Product);
    <main>
      <product-item></product-item>
    </main>

    <template id="product_item">
      <li class="cereal">
        <span class="cerealName" style="font-size: 1.3rem"></span>
      </li>
    </template>

almost 4 years ago · Santiago Trujillo Relatório

0

And you are also cloning the <template> twice with importNode and cloneNode

cloneNode is all you need, importNode is for importing from other documents.

And your component processed all products in one component; whilst you have multiple <product-item> in hour HTML

So I presume you want to make <product-item> display one product

I rewrote it a bit to (hopefully) let the code explain itself:

Note: the use of shadowDOM is probably overkill, it now blocks styling content.
Easily removed by removing 1 .attachShadow(...) and 3 .shadowRoot references.

customElements.define("product-item", class extends HTMLElement {
  connectedCallback() {
    let products = [{ name: "carrot", price: "6.99" },
                    { name: "blueberry", price: "6.99" }];

    let template = document.getElementById(this.nodeName).content;
    this.attachShadow({mode:"open"}).append(template.cloneNode(true));
    
    let product = products[this.getAttribute("nr")-1]; // UX starts at 1
    
    if (product) {
      this.shadowRoot.querySelector("b").textContent = product.name;
      this.shadowRoot.querySelector("span").innerHTML = `  US$ ${product.price}`;
    } else {
      this.shadowRoot.innerHTML = `No product`
    }
  }
});
<ul>
  <product-item nr=1></product-item>
  <product-item nr=2></product-item>
  <product-item nr=3></product-item>
</ul>

<template id="PRODUCT-ITEM">
  <li class="product">
    <b>NAME</b><span>PRICE</span>
  </li>
</template>

<style>
  body {
    color: red; /* "Inheritable" CSS styles not blocked! */
  }
  .product { /* blocked by shadowDOM */
    color:green; 
  }
</style>

If you do want one <my-products> creating all HTML in one go; innerHTML is shorter and faster

customElements.define("my-products", class extends HTMLElement {
  connectedCallback() {
    let products = [{ name: "carrot", price: "$ 6.99" },
                    { name: "blueberry", price: "$ 6.99" }];

    this
        //.attachShadow({mode:"open"})
        .innerHTML = products.map(product =>
          `<li class="product"><b>${product.name}</b> - ${product.price}</li>`
        ).join("");
  }
});
<my-products></my-products>

<style>
  .product {
    color:green;
  }
</style>

almost 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda