Overview

3 Making your component reuseable

This chapter explains how to make Web Components truly reusable by designing clear configuration surfaces and keeping components focused. It walks through a concrete example—a simple 3D search results component—showing how to wrap an HTTP request, render results, and style the output while keeping the component granular (display-only) so it can be composed with other UI pieces. The goal is to turn hard-coded behavior into flexible behavior that adapts via configuration, then apply the same ideas to an interactive slider component.

The chapter compares two complementary configuration approaches: component properties via getters/setters and HTML attributes. It shows how setters can trigger logic (like doSearch) while attributes enable declarative setup and avoid timing issues, then introduces attributeChangedCallback plus observedAttributes to react efficiently to changes (with attention to lowercase attribute names). Practical attribute utilities—hasAttribute, getAttribute, setAttribute—are used to add options like thumbheight and backgroundcolor, and to further generalize the component with baseuri and format for different endpoints. A small input field demonstrates how external UI can drive live updates by changing attributes.

Finally, it outlines best practices: avoid using attributes for rich, nested data; prefer property/attribute reflection so both HTML authors and JS consumers have a consistent API; and beware re-entrancy loops when syncing attributes and properties—treating attributes as the source of truth is a safe pattern. The slider is then upgraded with observedAttributes, attributeChangedCallback, and reflected getters/setters (value, backgroundcolor), plus event handling for dragging, so attribute updates and user interaction stay in sync. The chapter closes by noting the importance of encapsulating styling and structure to make the component shareable and maintainable.

Our HTTP response from Google Poly featuring assets and asset details
Our custom poly-search Web Component calling out to the Google Poly API with an API key and the search term "parrot." We get back a list of assets and thumbnails to display (next).
Our image results from poly.google.com before styling. They just flow down the page and force scrolling to see more than a few, because they are too large.
Our nicely styled and centered image grid. Images are smaller, have a nice gap between them, and are set against a subtle, off-white background with a gray border.
Using setters on our component from outside-in lets us perform logic and set a value, but also keep the component API simple.
Before an attributeChangedCallback is fired inside your component as a result of an attribute change on your component's markup, that attribute name must be in the observedAttributes list.
Re-entrancy is a bad way to implement property/attribute reflection. Setting the attribute when your getter is used causes an attributeChangedCallback to be fired, which can then set the property again, continuing on in an infinite loop.
The slider component so far
Using the slider component and watching the value attribute update in the dev tools

   Summary

In this chapter, we've expanded our Custom Element API methods repertoire to both connectedCallback and attributeChangedCallback. In the next chapter, we'll talk through the rest of the Web Component lifecycle in depth and compare it to similar component lifecycles on both the web and beyond.

Also in this chapter, you learned

  • How to use attributes to call an endpoint for a search service, with ideas on which attributes need to be watched and which don't, including how to actually watch the attributes in practice using the Web Components API
  • What reflection is and how it can make your component more robust, such that it can be used through its tag as well as through a custom JS API, and how to avoid the problem of re-entrancy
  • Strategies for when to use attributes versus a custom API and when to use both for a better developer experience for your component’s consumers

FAQ

What are the two main ways to make a Web Component configurable, and when should I use each?Use properties (getters/setters) and attributes. Attributes are great for declarative, HTML-based configuration and initial setup. Getters/setters shine for ergonomic use from JavaScript and can encapsulate logic (for example, running a search when a value changes). Many components support both and keep them in sync (reflection) so developers can choose either style.
How do I run code when an attribute changes?Implement attributeChangedCallback(name, oldVal, newVal) in your component class and return the list of attributes you care about from static get observedAttributes(). Inside the callback, check the attribute name and perform the update (for example, rerun a search when "searchterm" changes).
Why isn’t attributeChangedCallback firing in my component?You must whitelist attribute names in static get observedAttributes(). If the attribute isn’t listed there, changes won’t trigger attributeChangedCallback. Example: static get observedAttributes() { return ['searchterm']; }
Are attribute names case-sensitive?HTML attribute names are case-insensitive, but the name you receive in attributeChangedCallback is lowercase. To avoid confusion, define and use attribute names in lowercase consistently (for example, "searchterm", "apikey").
How do I avoid running logic before my component is properly configured?Add guards in your methods. For example, before making a request, check that required attributes exist: if (this.getAttribute('apikey') && this.getAttribute('searchterm')) { /* do work */ }. This prevents premature work during initialization.
What is property/attribute reflection and how do I implement it safely?Reflection keeps a property and its corresponding attribute in sync so either API can be used. A simple approach is to treat the attribute as the source of truth: - getter returns getAttribute('name'); - setter calls setAttribute('name', value); Avoid setting a property inside attributeChangedCallback that sets the attribute again, which can cause an infinite loop.
When should I use hasAttribute, getAttribute, and setAttribute?- hasAttribute(name): check if a configuration value was provided (useful for optional settings and defaults). - getAttribute(name): read values for logic (for example, sizes, colors, endpoints). - setAttribute(name, value): update the component declaratively (for example, in response to user input) and let reflection/observers react.
How can I connect an external input to drive my component?Listen for input changes (for example, onchange on a text field) and set a component attribute with the new value (element.setAttribute('searchterm', value)). The component’s attributeChangedCallback reacts and updates itself.
How can I make styling and sizing configurable without heavy logic?Expose simple attributes (for example, "thumbheight", "backgroundcolor"). In connectedCallback, read them with hasAttribute/getAttribute, apply defaults if missing, and use the values when rendering (for example, image widths/heights, inline styles). For values that don’t need to change at runtime, you can skip observing them.
Should I pass complex (rich) data via attributes?Prefer not to. Attributes are best for simple scalar values (strings, numbers, booleans). For arrays/objects, use properties or dedicated methods to pass data. While you can JSON.stringify data into an attribute, it harms readability, tooling, and maintainability.

pro $24.99 per month

  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose one free eBook per month to keep
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime

lite $19.99 per month

  • access to all Manning books, including MEAPs!

team

5, 10 or 20 seats+ for your team - learn more


choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Web Components in Action ebook for free
choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Web Components in Action ebook for free
choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Web Components in Action ebook for free