Reminder about Web Components and Attributes
source link: https://www.raymondcamden.com/2023/03/09/reminder-about-web-components-and-attributes
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Reminder about Web Components and Attributes
After my post yesterday about web component lifecycle events, I had an interesting conversation with Thomas Broyer on Mastodon. He brought up an issue with web components that I covered before on this blog, but as it was a very appropriate thing to discuss immediately after yesterday's post, I thought a bit of repetition would be ok. And heck, I'll take any chance to write more web component code as it gives me more practice.
So as a reminder, yesterday's post specifically dealt with what code is best used in a web component's constructor versus the connectedCallback
event. Specifically, it dealt with the use case of checking attributes and handling web component elements created via JavaScript. To be clear, I don't mean the definition of the web component, but creating an instance of one, like so:
let mc = document.createElement('my-component');
document.body.appendChild(mc);
While I didn't bother setting a title in that example, I could have done so like this:
let mc = document.createElement('my-component');
mc.setAttribute('title','My title');
document.body.appendChild(mc);
And it works as expected. But here's an interesting question. What if later on I change the title? Imagine this code:
setTimeout(() => {
console.log('timer done, lets do this');
mc.setAttribute('title','New title');
console.log(`title for the mc is ${mc.getAttribute('title')}`);
}, 3 * 1000);
When run, what will it do? Check out the CodePen below to see:
As you can see, it does not work. Remember you can open your browser's console here if you want to see the messages. It will clearly say that the title attribute matches the update, but that's what you'll see reflected in the DOM.
The good (?) news is that this is completely expected and easily (for the most part) addressed. When defining a web component, you need to define which attributes you care about it (in terms of them changing) and write code to listen for those changes.
The first part is simple:
``js static get observedAttributes() { return ['title'] };
The next part involves adding an event handler named `attributeChangedCallback`:
```js
attributeChangedCallback(name, oldValue, newValue) {
console.log(`changing the value of ${name} from ${oldValue} to ${newValue}`);
}
If you try this, you'll see that it's fired multiple times. I had a "hard-coded" instance of the component in the DOM and it will message that the title is changing from null to the hard-coded value, reflecting the immediate change of the web component being added to the DOM. You will also see this run with the instance of the component created in JavaScript.
Now for the fun part. The event handler needs to actually update the display to reflect the new value. In the first iteration of my example component, I skipped the Shadow DOM and just wrote it out directly to the main DOM. Since I now need to (possibly) update the DOM multiple times, I made two more changes. I switched to the Shadow DOM and built a new method, updateDisplay
, that handles updating the display. Here's the entire class:
class MyComponent extends HTMLElement {
constructor() {
super();
console.log('constructor called');
const shadow = this.attachShadow({ mode: "open" });
const div = document.createElement('div');
const h2 = document.createElement('h2');
div.appendChild(h2);
shadow.appendChild(div);
}
connectedCallback() {
console.log('connected callback called');
if(!this.getAttribute('title')) this.setAttribute('title', 'No title');
this.updateDisplay();
}
updateDisplay() {
this.shadowRoot.querySelector('h2').innerText = `My Component: ${this.getAttribute('title')}`;
}
static get observedAttributes() { return ['title'] };
attributeChangedCallback(name, oldValue, newValue) {
console.log(`changing the value of ${name} from ${oldValue} to ${newValue}`);
this.updateDisplay();
}
}
Notice that updateDisplay
just uses querySelector
to find its h2
node and update the text. Now our code that updates the title after a few seconds will work correctly:
If you don't see the switch, just click the "Rerun" button on the bottom right. Anyway, as I said, I've discussed this before, but it definitely tripped me up the first time I ran into it so hopefully this helps others!
Photo by Chris Lawton on Unsplash
Recommend
-
8
ARIA Roles and Attributes: How to Actually Use Them September 8, 2016 If you’re a web developer, then there’s a chance that you’ve heard of ARIA roles and attributes before.
-
9
4 Methods to Add Conditional Attributes to React ComponentsDifferent methods and best practices of using conditional attributes or props with ReactToday, conditional attributes are widely used...
-
3
C# Caller Attributes Make Tracing and Logging Easier If you wanted to include information about your source code in a trace message, there would be quite a lot of prep work to do before you could actually write a message out. Let’s u...
-
8
George Griffiths Posted on Nov 6 ...
-
6
Legend order and group attributesIn this post, I will show you how to control the order of the entries in a legend and explicitly control the correspondence between groups and style elements in PROC SGPLOT. In many cases, the colors that are...
-
8
Some attributes in ARIA are boolean(-like). These attributes may seem a lot like boolean attributes in HTML, but there are some important differences to be aware of.
-
2
Reminder: you can `suggest` titles and tags This is a friendly reminder that users above a certain karma level (currently 10) can use the suggest link under each submission to provide input to titles...
-
3
RMNDMVoice notes and reminder appPayment RequiredTrack your notes & events via voice. We will always remind you!
-
5
January 19th, 2023 Forms on the web are an opportunity to make big improvements to the user experience with very little effort. The effort can be as little as sprinkling in a smattering of humble HTML attributes. But th...
-
2
Creating Web Accessibility (3 Part Series) Back on the topic of accessi...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK