Search code examples
javascripthtmlcssweb-component

Web component only rendered once


*** Figured out 1 working solution, answer below.***

This is my first time using Web Components. I have created a Web Component named article-component. When I add article-component to my HTML, it works. When I add another article-component, it does not render completely. The content is not rendered, just an outline. What's interesting is that in the elements, all the invisible shadow-roots are empty.

 screenshot

My code,

index.html

<!doctype html>

<html lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <title>title</title>

  <link rel="stylesheet" href="css/style.css">
  <script src="js/components/article.js"></script>

</head>

<body>
  <div id="screen">
    <div class="page">
      <div class="title">
        <h1>yesterday</h1>
      </div>
      <div class="body">
        <article-component></article-component>
        <article-component></article-component>
        <article-component></article-component>
        <article-component></article-component>
      </div>
    </div>
  </div>
  <script src="js/script.js"></script>
</body>

</html>

style.css

/* Reset CSS for browser consistency */
html,
body,
h1,
h3,
h4,
p {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 20px;
  font-weight: 400;
}

/* Screen */
#screen {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  background-color: #ffffff;
}

/* Page */
.page {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.title {
  width: 100%;
  text-align: center;
  padding: 8px;
  margin: 8px;
}

.body {
  width: 100%;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: center;
}

/* Article */
article-component {
  width: 33%;
}

@media screen and (orientation: portrait) {
  article-component {
    width: 80%;
  }
}

/* Text */
h1 {
  font-size: 2rem;
  font-weight: normal;
}

h3 {
  font-size: 1.2rem;
  font-weight: lighter;
  line-height: 1.8rem;
}

h4 {
  width: auto;
  font-size: 1rem;
  font-weight: 500;
}

p {
  letter-spacing: 1px;
  line-height: 1.5rem;
}

article.js

const articleTemplate = document.createElement("template");
articleTemplate.innerHTML = `

<link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" href="css/components/article.css">

<div class="article">
    <div class="heading">
        <h3>Indian Migrant Labourers Covid19 Crisis</h3>
    </div>
    <div class="content">
        <p>
            Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum gravida efficitur mi vel malesuada.
            Nunc id nulla odio. Ut convallis tristique vehicula. Suspendisse potenti. Mauris tempor, ligula ut tincidunt
            venenatis, ex enim placerat arcu, nec venenatis urna sem varius libero. Quisque quis augue eu neque euismod
            luctus. Integer mauris neque, vulputate sit amet velit quis, hendrerit aliquam risus. Vivamus ultrices neque
            lorem, nec laoreet elit viverra non.
        </p>
    </div>
    <div class="sources">
        <div class="source">
            <h4>[1]&nbsp</h4>
            <h4>Lorem ipsum dolor sit amet.</h4>
        </div>
    </div>
</div>
`;

class Article extends HTMLElement {
  constructor() {
    super();
  }

  connectedCallback() {
    const shadowRoot = this.attachShadow({ mode: "open" });
    shadowRoot.appendChild(articleTemplate.content);
  }
}

customElements.define("article-component", Article);

article.css

.article {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 8px;
}

.heading {
  padding: 8px;
}

.content {
  padding: 4px;
}

.sources {
  width: 100%;
  display: flex;
  flex-direction: column;
  margin-left: 8px;
  margin-top: 8px;
}

/* Source */
.source {
  width: 100%;
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
}

Solution

  • Editing the following line in article.js -> connectedCallback() worked:

    shadowRoot.appendChild(articleTemplate.content);
    

    to

    shadowRoot.appendChild(articleTemplate.content.cloneNode(true));
    

    I do not know exactly why.