I am learning web components and am building a dynamic list to get the hang of them. Having got it working, I read that it's best to attach the shadow root using the connectedCallback
method. However, having tried to do this, I get a bunch of errors I can't fix.
Also, The way I am setting a simple attribute to a label seems a bit long winded: is there a simpler way just to pick up an attribute and display it as a label?
This is my working example:
const template = document.createElement('template');
template.innerHTML = `
<style>
:host {
display: block;
font-family: sans-serif;
text-align: center;
}
button {
border: none;
cursor: pointer;
}
ul {
list-style: none;
padding: 0;
}
</style>
<h1>To dos</h1>
<lable id="lable1"></lable>
<select></select>
`;
class TodoApp extends HTMLElement {
constructor() {
super();
this._shadowRoot = this.attachShadow({ 'mode': 'open' });
this._shadowRoot.appendChild(template.content.cloneNode(true));
this.$todoList = this._shadowRoot.querySelector('select');
this.label1 = this._shadowRoot.getElementById('lable1')
}
static get observedAttributes() {
return ['att1'];
}
attributeChangedCallback(name, oldValue, newValue) {
this.label1.innerText = this.getAttribute('att1');
}
renderTodoList() {
this.$todoList.innerHTML = '';
this.todosArray.forEach((todoP) => {
let $todoItem = document.createElement('option');
$todoItem.text = todoP.text;
$todoItem.value = todoP.id;
this.$todoList.appendChild($todoItem);
});
}
set todos(value) {
this.todosArray = value;
this.renderTodoList();
}
}
window.customElements.define('to-do-app', TodoApp);
When I add a connectedCallback()
method and create the shadow dom there, I get a bunch of errors.
My markup is just:
<to-do-app att1="value 1 attribute"></to-do-app>
I tried this:
class TodoApp extends HTMLElement {
constructor() {
super();
this.label1 = '';
}
connectedCallback() {
this._shadowRoot = this.attachShadow({ 'mode': 'open' });
this._shadowRoot.appendChild(template.content.cloneNode(true));
this.$todoList = this._shadowRoot.querySelector('select');
this.label1 = this._shadowRoot.getElementById('lable1')
}
static get observedAttributes() {
return ['att1'];
}
attributeChangedCallback(name, oldValue, newValue) {
this.label1.innerText = this.getAttribute('att1');
}
But get the error:
TypeError: can't assign to property "innerText" on "": not an object