Web Components and You Part 2: Attributes and Reactivity
HTML is powerful because it has attributes to customize elements. You can
specify why type of input by include type="_type_"`
inside the
<input />
tag. You can set properties like whether a
checkbox is checked by using the checked
boolean attribute.
So of course custom elements are going to use attributes. They also allow a component to react when attributes change.
First, take a look at accessing a simple attribute "my-attr":
We can access attributes by using element.getAttributes('attr')
,
and in this example we're just putting it in the DOM.
What happens if we change the attribute?
If you open dev tools and manually change the value of the attribute you'll see that it doesn't automatically update...
We have to do more work to wire up reactivity.
An important note here...
If you're used to using any framework, this may be something
you've never had to think about. In HTML, the attributes we use always have a
string value- which is why weird things happen when you have a checkbox and
you say disabled="false"
and it's disabled.
So how do we get a component to react to an attribute changing?
Let's go back to the example above where we take an attribute and simply put
the attribute value in as text in our component. The first requirement is to
"register" your attribute with a static property
observedAttributes
. Once you have the attribute registered, you
can add a method attributeChangedCallback()
to your component
class, and that will be called every time an attribute changes.
Now, I'm going to move my template rendering into its own method
render()
. This makes it much easier to re-render the template
when an attribute changes. I'm also doing a check to see if the name of the
changed attribute is "my-attr". This isn't strictly necessary, but it's
showing what you get in this method when attributes do change.
One thing we're doing is also checking if the shadow root has been added yet.
There are cases where attributes are parsed and the
attributeChangedCallback
is called even before
connectedCallback
is called. So, we just early exit if that's the
case!
Go ahead, give it a try below! Inspect our element, change the attribute, and you should see it update its dom and change!
That was a lot of work!
Yeah, admittedly, that is a lot of work. Web components give us the primitives to do this sort of thing, but wouldn't it be nice to just treat these things like a framework component? Meaning, is there a a way we can just update data and let the template update like in React or Vue or Svelte? The answer's yes! In the next post I'll be introducing Lit and things will get a lot easier!