I am about to learn vanilla js web components. I could successfull render some elements generated by webcomponents, now I would like to give it some design and put it inside a sidebar. However I am not sure if this is webcomponents or just design problem, the elements won´t display anymoer after adding the sidebar.
Maybe you could take a look at my code and give me some hints, where I am causing the problem?
@Edit: As suggested in comment I have put it in fiddle, so you can try it out. Now I understeand the behavior even less, then In fiddle it looks kind as it should and on my local machine not.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>DiceArea</title>
</head>
<body>
<script type="module" src="./index.js"></script>
</body>
</html>
window.addEventListener('load', () => {
getUsers();
});
function getUsers() {
const users = ["player1", "player2", "player3", "player4", "player5"];
const nav = document.createElement("player-nav");
nav.setAttribute("class", "sidenav")
document.body.appendChild(nav);
users.forEach(user => {
user = document.createElement('table-user');
nav.appendChild(user);
user.addEventListener("click", () => {
alert("lol")
})
})
}
class User extends HTMLElement {
constructor() {
super();
this.shadow = this.attachShadow({mode: 'open'});
}
connectedCallback() {
this.user();
}
user() {
this.shadow.innerHTML = `
<style>
.sidenav {
height: 100px;
width: 100px;
position: fixed;
background-color: #0000;
overflow-x: hidden;
padding-top: 20px;
}
.avatar {
width: 90px;
height: 90px;
border-radius: 10%;
}
</style>
<img src="html/aavatar.png" alt="Avatar" class="avatar">`
}
}
customElements.define("table-user", User);
At first sight I see 2 possible problems:
You are doing .createElement('player-nav')
but never defined that Custom Element
You are doing nav.appendChild()
IF nav
is an element with shadowDOM, you have to do nav.shadowRoot.appendChild()
because the original element content is now 'lightDOM'
see: Difference between Light DOM and Shadow DOM
Your code is still very traditional/oldskool DOM manipulation.
I butchered your JSFiddle into a (quick) example showing some Web Components concepts you can play with:
<template id=TABLE-PLAYERS>
<style>
:host {
display: block;
background: grey;
--clickedColor: green;
}
</style>
<h3>Players</h3>
</template>
<template id=PLAYER-NAV>
<style>
:host {
display: block;
background: lightgreen;
}
* {
float: left
}
:host(.clicked){
background:var(--clickedColor);
}
.name{
font-size:2em;
}
</style>
<slot name=avatar></slot>
<div>
<slot class=name name=username></slot>
</div>
</template>
<table-players id=Players></table-players>