Skip to main content Accessibility Feedback

More ways to instantiate Web Components

Last week, we looked at different ways to setup the HTML in a Web Component.

One of the challenges with running your code in the constructor() is that sometimes the custom element is created, but none of the nested HTML inside it is ready yet.

We looked at a few different ways to fix that, but today, I wanted to share two more.

Let’s dig in!

🚀 I’m launching a Web Component course! Learn how to create your Web Components from scratch, master best practices, learn when to use them, and more. Pre-order today and get $100 off.

Using requestAnimationFrame() or setTimeout()

One option to work around this is to try to setup your Web Component, and if any required HTML is missing, using requestAnimationFrame() or setTimeout() to try again after the next browser paint.

For example, imagine that you have a setup() method in your Web Component class that setups the DOM and adds all of the interactivity.

/**
 * Setup the Web Component when it's connected to the DOM
 */
setup () {

	// Set the properties
	this.button = this.querySelector('button');
	this.count = parseFloat(this.getAttribute('start')) || 0;
	this.step = parseFloat(this.getAttribute('step')) || 1;
	this.text = this.getAttribute('text') || 'Clicked {{count}} Times';

	// Listen for click events
	this.button.addEventListener('click', this);
	
	// Announce UI updates
	this.button.setAttribute('aria-live', 'polite');

}

After setting this.button, you can check if the property exists.

If not, you can use requestAnimationFrame() to run this.setup() again during the next browser paint, and bail on the rest of the setup until then.

/**
 * Setup the Web Component when it's connected to the DOM
 */
setup () {

	// Get the button
	this.button = this.querySelector('button');

	// If it doesn't exist, try again after the next paint
	if (!this.button) {
		requestAnimationFrame(() => {
			this.setup();
		});
		return;
	}

	// Set the remaining properties
	// ...

}

Here’s a demo.

Use a [ready] attribute

Last week, we learned that Web Components can automatically detect when attributes are added, removed, or changed.

We can use that built-in functionality to detect when a [ready] attribute is added to our component, and run the setup when it happens.

// Define the attributes to observe
static observedAttributes = ['ready'];

/**
 * Setup the component when the [ready] attribute is added
 */
attributeChangedCallback () {
	this.setup();
}

Here’s another demo.

Which approach should you use?

If I were building Web Components for a design system that might be used by different developers in different ways, I’d likely combine a few of these approaches to give my devs lots of options…

  • Automatic instantiation when the element is created
  • A this.setup() method that can be manually run
  • Using requestAnimationFrame() to retry a few times (I’d maybe stop after a few failed attempts)
  • A [ready] attribute

Which approach do you like best?