DEV Community

Discussion on: Web Fundamentals: Web Components Part 2

Collapse
 
darkwiiplayer profile image
𒎏Wii 🏳️‍⚧️

You might have noticed that the timer declaration has moved from the constructor to the connectedCallback, and this was to simplify passing in the dynamic interval delay value, which would only be queryable once the element is mounted (or connected)

There's two things I want to add here:

  1. Setting up the timer in the constructor and removing it in the connectedCallback would have meant the component would have stopped working if it was ever removed from the document and inserted elsewhere. Setting it in the connectedCallback to re-start it when re-attaching is the correct way about this.

  2. It is not entirely correct that the attribute for the delay value is only queryable when the element is mounted. If the element has already been parsed by the time the custom element is defined, the constructor will have full access to the element and its children, including attributes. Only if the custom element is already defined before the element is parsed, the constructor will run before any of the attributes or child elements have been parsed.

Note: This is equivalent static observedAttributes = ["x-interval"];, and if you had more than one attribute to track, you would comma-separate them in that array.

If you already have an attrs attribuet, then I would hope nobody would actually comma-separate them and instead just write something like this:

static observedAttributes = Object.keys(Timer.attrs)
Enter fullscreen mode Exit fullscreen mode

Last but not least, the final version of the component would behave somewhat inconsistently. Detaching the component would initially pause the counting. Updating the interval attribute would then resume the counting. Connecting the element again would then start a second interval that could never be cancelled anymore and would continue to count up until the page is closed.

An easy way to fix this would be to just check if the object is actually connected in the attributeChangedCallback 😁

Collapse
 
hasanhaja profile image
Hasan Ali

Thank you very much for your feedback.

Setting it in the connectedCallback to re-start it when re-attaching is the correct way about this.

This makes so much sense, and I don't know how I missed this!

It is not entirely correct that the attribute for the delay value is only queryable when the element is mounted. If the element has already been parsed by the time the custom element is defined, the constructor will have full access to the element and its children, including attributes. Only if the custom element is already defined before the element is parsed, the constructor will run before any of the attributes or child elements have been parsed.

This has taken me a quite a while to wrap my head around. I had someone else also flag this for me when I did the first post, and to be honest it hasn't clicked until now. I'll work on the correction and update the post. Thank you!

static observedAttributes = Object.keys(Timer.attrs)

Good shout! I'll add that in too and signpost that by doing so all of your attributes will be tracked, which is probably what you'd want most of the time.

Detaching the component would initially pause the counting. Updating the interval attribute would then resume the counting. Connecting the element again would then start a second interval that could never be cancelled anymore and would continue to count up until the page is closed.

Great catch! I definitely didn't play that scenario out. I'll make the correction!

Honestly, thank you so much for taking the time to read the post and give me feedback! Greatly appreciate it.