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…


This content originally appeared on Raymond Camden and was authored by Raymond Camden

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:

See the Pen WC Tests (5) by Raymond Camden (@cfjedimaster) on CodePen.

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:

``jsstatic get observedAttributes() { return ['title'] };

The next part involves adding an event handler named `attributeChangedCallback`:```jsattributeChangedCallback(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:

See the Pen WC Tests (5) by Raymond Camden (@cfjedimaster) on CodePen.

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


This content originally appeared on Raymond Camden and was authored by Raymond Camden


Print Share Comment Cite Upload Translate Updates
APA

Raymond Camden | Sciencx (2023-03-09T18:00:00+00:00) Reminder about Web Components and Attributes. Retrieved from https://www.scien.cx/2023/03/09/reminder-about-web-components-and-attributes/

MLA
" » Reminder about Web Components and Attributes." Raymond Camden | Sciencx - Thursday March 9, 2023, https://www.scien.cx/2023/03/09/reminder-about-web-components-and-attributes/
HARVARD
Raymond Camden | Sciencx Thursday March 9, 2023 » Reminder about Web Components and Attributes., viewed ,<https://www.scien.cx/2023/03/09/reminder-about-web-components-and-attributes/>
VANCOUVER
Raymond Camden | Sciencx - » Reminder about Web Components and Attributes. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2023/03/09/reminder-about-web-components-and-attributes/
CHICAGO
" » Reminder about Web Components and Attributes." Raymond Camden | Sciencx - Accessed . https://www.scien.cx/2023/03/09/reminder-about-web-components-and-attributes/
IEEE
" » Reminder about Web Components and Attributes." Raymond Camden | Sciencx [Online]. Available: https://www.scien.cx/2023/03/09/reminder-about-web-components-and-attributes/. [Accessed: ]
rf:citation
» Reminder about Web Components and Attributes | Raymond Camden | Sciencx | https://www.scien.cx/2023/03/09/reminder-about-web-components-and-attributes/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.