class Table extends HTMLElement {
// attributes
constructor() {
super();
this.name = 'undefined';
this.icon = 'bi-patch-question';
}
// component attributes
static get observedAttributes() {
return ['name', 'icon', 'properties'];
}
// attribute change
attributeChangedCallback(property, oldValue, newValue) {
if (oldValue == newValue) return;
this[ property ] = newValue;
}
connectedCallback() {
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML = `
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css">
<div >
<table >
<tr>
<caption>${this.name}<i ></i></caption>
</tr>
<!-- here should be the em-tds -->
</table></div>
<style>
.card {
border: 1px solid lightgray;
border-radius: 15px;
margin: 10px 0;
padding: 15px;
}
table {
width: 100%;
border-collapse: collapse;
}
tr {
border-top: 1px solid lightgrey;
}
tr:first-child {
border: none;
}
td {
width: 100%;
padding: 7px;
font-size: 18px;
vertical-align: middle;
}
caption {
position: relative;
font-family: ExtraBold;
padding: 7px;
margin-bottom: 5px;
text-align: left;
font-size: 18px;
text-decoration: 2px underline;
}
caption i {
position: absolute;
right: 6px;
font-size: 22px;
}
</style>
`
}
}
class TableTds extends HTMLElement {
// attributes
constructor() {
super();
this.name = 'undefined';
this.value = 'undefined';
}
// component attributes
static get observedAttributes() {
return ['name', 'value'];
}
// attribute change
attributeChangedCallback(property, oldValue, newValue) {
if (oldValue == newValue) return;
this[ property ] = newValue;
}
connectedCallback() {
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML = `
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css">
<td>${this.name}</td>
<td>${this.value}></td>
`
}
}
customElements.define('em-table', Table);
customElements.define('em-td', TableTds);
<em-table name="test">
<em-td name="test" value="10"></em-td>
<em-td name="test" value="10"></em-td>
</em-table>
I'm working on new web-components for my plattform and ran in some kind of issue. Creating web-components works fine for me but I wanted to create sub-components inside the tags of a web-component. Obviously that has not worked, because the component is protected from everything else...
In my case its about a table web-component, in which I would like to have the html-tds as subcomponents, to later use them properly.
I've tried to use slots but that has not worked...
CodePudding user response:
This should get you started, you need to add more yourself.
Main point is not to wrap Everything in a shadowDOM,
let your em-td
find their "table", without having to pierce UP through a shadowroot boundary
with:
connectedCallback() {
this.closest("em-table")
.shadowRoot
.querySelector("table")
.append(this.tr);
}
Working snippet:
Note: using a declarative shadowDOM <template shadowroot="open">
for em-table
here.
You can move it all to its constructor
if you don't want to start from SSR/HTML
<em-table name="test">
<template shadowroot="open">
<div >
<table >
<caption></caption>
</table>
</div>
<style>
tr{background:pink}
</style>
</template>
<em-td name="test1" value="10"></em-td>
<em-td name="test2" value="20"></em-td>
</em-table>
<script>
customElements.define('em-table', class extends HTMLElement {
caption(name, icon) {
let html = `${name}<i ></i>`;
this.shadowRoot.querySelector("caption").innerHTML = html;
}
connectedCallback() {
this.caption('caption', 'bi-patch-question');
}
static get observedAttributes() {
return ['name', 'icon', 'properties'];
}
attributeChangedCallback(property, oldValue, newValue) {
if (oldValue == newValue) return;
this[property] = newValue;
}
});
customElements.define('em-td', class extends HTMLElement {
static get observedAttributes() {
return ['name', 'value'];
}
constructor() {
super();
this.tr = document.createElement("tr");
this._name = document.createElement("td");
this._value = document.createElement("td");
this.tr.append(this._name, this._value);
}
attributeChangedCallback(property, oldValue, newValue) {
if (oldValue == newValue) return;
this[property] = newValue;
}
set name(v) {
this._name.innerText = v;
}
set value(v) {
this._value.innerText = v;
}
connectedCallback() {
this.closest("em-table")
.shadowRoot.querySelector("table")
.append(this.tr);
}
});
</script>
And be aware:
From the <TR>
documentation on MDN:
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tr
Permitted parents
<table>
(only if the table has no child<tbody>
element, and even then only after any<caption>
,<colgroup>
, and<thead>
elements); otherwise, the parent must be<thead>
,<tbody>
or<tfoot>
So
<em-table>
<tr>
is not valid HTML