Sunday, November 15, 2015

Web components lifecycle methods 3: filling in the gaps

As we have seen in my previous posts the web component standard defines only four lifecycle methods:

  1. createdCallback  when the element is created, but possibly not attached to a document
  2. attachedCallback  when the element is added to a document
  3. detachedCallback when the element is removed from the document
  4. attributeChangedCallback, when an attribute is changed
They are also all callbacks: they are called after the standard processing, so you cannot override the standard processing. This is a very small model. If you compare with the lifecycle for an Android Activity you will see that the activity also has calls like:
  • onPause() Another activity comes into the forground
  • onResume() User returns to the activity
  • onStop() The activity is no longer visible
There are no corresponding callbacks in the web component standard. Most importantly ther is no callback method for when your element is displayed to the user. The attachedCallback will be called when your element is added to the DOM, but it might very well be hidden, specially since the practice to use hidden DOM elements for things like tabs, menues etc is so common in the HTML world. And there is no visibleCallback that is called when your element is shown.

Filling the gap 1: listen to the resize event

First step is probably to listen to the 'resize' event. This event is trigger when the browser window is resized, so it's pretty likely that you need to listen to it anyhow, if you ned to re-render or something when the window size changes. The right place to set up this listener is in attachedCallback:
                window.addEventListener("resize", me.redraw);
And you should remove it in detachedCallback:
window.removeEventListener("resize", this.redraw);
Now this might do, if you can make sure that your page triggers a resize event when the visibility of your element changes (like some sort of tabbing, page navigation etc). But it is a bit of overkill, since the resize event will go to all elements in the page and not just the ones affected by the change. It is also far from certain that the components you use do trigger resize events, so you might need to patch them.

Filling the gap 2: expose a draw method

This approach is more precise: you expose a draw method (or event) on your element, and the code in the page calls this method when needed. If you look at Googles implementation of web components for Google Charts this is the approach they have taken with the drawChart() method. Following this approach will simplify for users that use your component and have experience from Google charts. Unfortunately there is as far as I know no standard for this, so you cant really count on other components calling this method.

Of course you can combine these two approaches, expose a draw() method on your element, and then listen to the resize event and call the method when it occurs.