Why isn’t my web site being created/rendered?

Asked

Viewed 54 times

1

I’m trying to create a button following the documentation Webcomponents however mine button is not being rendered on the page.

I created a simple button extending the resources of a HTMLButtonElement and applies an effect of ripple when clicked:

When I open the page, only the "test" is rendered, mine web component is not shown in the template and the console does not print the message left on constructor().

Because my component is not being created/shown?

class MyButton extends HTMLButtonElement {
  constructor() {
    super();
    console.log("entrou no construtor");
    this.addEventListener("click", (e) => this.rippe(e.offsetX, e.offsetY));
  }

  drawRipple(x, y) {
    let div = document.createElement("div");
    div.classList.add("ripple");
    this.appendChild(div);
    div.style.top = `${y - div.clientHeight / 2} px`;
    div.style.left = `${x - div.clientWidth / 2} px`;
    div.style.backgroundColor = "currentColor";
    div.classList.add("run");
    div.addEventListener("transitioned", () => div.remove());
  }
}
window.customElements.define("my-button", MyButton, { extends: "button" });
button {
  width: 150px;
  height: 150px;
  border-radius: 50%;
  color: #fafafa;
  background-color: green
}
<!DOCTYPE html>
<html lang="pt">
  <head>
    <script type="text/javascript" src="./my_button.js"></script>
    <script type="stylesheet" src="./my_button.css"></script>
  </head>
  <meta charset="UTF-8" />
  <title>web components</title>
  <meta name="viewport" content="width=device-width,initial-scale=1" />
  <body>
    <my-button>teste button</my-button>
  </body>
</html>

1 answer

1


The problem is very simple: you are not applying the style :)

Note that in css, you used the "button" selector, but the element is created/rendered using the "my-button" tag, so the selector must have that tag name.

It is a simple selector problem, this is not because it was to create a "new" button, can create any element and stylize without having to render, that’s because the HTML is a line of markup, if there is style for markup, it will be rendered:

class MyButton extends HTMLButtonElement {
  constructor() {
    super();
    this.addEventListener("click", (e) => this.rippe(e.offsetX, e.offsetY));
  }

  drawRipple(x, y) {
    let div = document.createElement("div");
    div.classList.add("ripple");
    this.appendChild(div);
    div.style.top = `${y - div.clientHeight / 2} px`;
    div.style.left = `${x - div.clientWidth / 2} px`;
    div.style.backgroundColor = "currentColor";
    div.classList.add("run");
    div.addEventListener("transitioned", () => div.remove());
  }
}
window.customElements.define("my-button", MyButton, { extends: "button" });
my-button {
  width: 150px;
  height: 150px;
  border-radius: 50%;
  color: #fafafa;
  background-color: green
}

meu-novo-elemento {
   display: block;
   border: solid 1px #000;
   border-radius: 30px;
   background-color: #dcf4ff;
   color: #333;
   font-family: Arial;
   font-size: 1.3em;
   padding: 5px;
   margin-top: 10px;
   text-align: center;
   height: 20px;
   width: 100px;
}

meu-novo-elemento:hover {
  background-color: blue;
  color: #fff
}
<my-button>teste button</my-button>
<meu-novo-elemento>Teste</meu-novo-elemento>

See that if you inspect the HTML, the elements have the tag names with which they were defined, so the selector should follow:

inserir a descrição da imagem aqui

EDIT:
About the code not writing in the console what is written in the constructor (thanks to @Luizfelipe for the comment), I did several tests and reached the following conclusion:

only elements inherited from HTMLElement pass "automatically" by the constructor when they are registered, without passing the parameter { extends: "tipo" }.

That may or may not be right, but the tests reflect that.
How did I test? I created a code on jsfiddle (here is the original) that I copied on snippet below and I could prove it. I took examples from the internet and created 3 different webcomponents, inheriting from HTMLElement, HTMLButtonElement and HTMLParagraphElement.

I tested in the browsers Chore, Firefox and Opera and in all was the same result, Edge generated error when registering the line Component window.customElements.define. In all test cases, all elements only go through the constructor when it is done new, and the widget is created manually. Only the widget inherited from HTMLElement passes by the constructor when it is registered. Below the code that exemplifies it:

class MyButton extends HTMLButtonElement {
  constructor() {
    super();
    console.log("construtor MyButton");
    this.addEventListener("click", (e) => this.rippe(e.offsetX, e.offsetY));
  }

  drawRipple(x, y) {
    let div = document.createElement("div");
    div.classList.add("ripple");
    this.appendChild(div);
    div.style.top = `${y - div.clientHeight / 2} px`;
    div.style.left = `${x - div.clientWidth / 2} px`;
    div.style.backgroundColor = "currentColor";
    div.classList.add("run");
    div.addEventListener("transitioned", () => div.remove());
  }
}

class WordCount extends HTMLParagraphElement {
  constructor() {
    super();
    console.log("construtor WordCount");
  }
}

class PopUpInfo extends HTMLElement {
  constructor() {
    super();
    console.log("construtor PopUpInfo");
  }
}

// aqui, só o PopUpInfo (HTMLElement) passa pelo construtor
console.log("Registrar os components:");
window.customElements.define("my-button", MyButton, { extends: "button" });
window.customElements.define('word-count', WordCount, { extends: 'p' });
window.customElements.define('popup-info', PopUpInfo);


// aqui, usando new, todos passam pelo construtor
console.log("---------------------");
console.log("Instanciar os components:");

let popup = new PopUpInfo();
document.body.appendChild(popup);

let paragr = new WordCount();
document.body.appendChild(paragr);

let button = new MyButton();
document.body.appendChild(button);
<word-count>word-count</word-count>
<br />
<my-button>button</my-button>
<br />
<popup-info>popup-info</popup-info>

  • 1

    Ricardo, would you explain why console.log("entrou no construtor") seems not to be running? It also seems to me a question of the question.

  • 1

    hello Luiz. So I haven’t had time to write this in the reply but, I did tests with this and, when it extends a "generic" component of HTMLElement, passes through the manufacturer, any other more specific, as HTMLButtonElement does not pass, only when it is instantiated explicitly, with new, hence the console.log not work. I saw several examples of this on the internet, all with constructor using specific elements, but in my tests none worked, confirming the behavior of the question. I will test in other browsers to confirm, because so far only tested in Chrome

  • 1

    @Luizfelipe edited the question and put the tests I did, it was very interesting

  • Thanks for the @Ricardopunctual clarifications one of the things I noticed is that when using new() the style is not applied (I believe that because in this case it is rendered in the gift with the extended element name, example <button> and not <my-button>, strange.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.