Mind Lifecycle When Extending LWC

Written by
Published on
April 19, 2021
Note: Generative AI was used to create this content

Extension Caveats

Row-click handling is not currently supported by Salesforce’s base Lightning-Datatable component. In a previous post, we explored extending the component to achieve this functionality. This is powerful, but there are hangups! Lets examine one of these sneaky side-effects.

The Example

// DatatablePlus.jsimport LightningDatatable from  'lightning/datatable';
   
export default class DatatablePlus extends LightningDatatable {

renderedCallback() {
   
if (this._hasRendered) {
       
return;
   }

   
const table = this.template.querySelector('tbody');
   table.addEventListener(
       'click',
       (e)
=> { console.log(e.target.tagName + ' was clicked.'); }
   );
       
   
this._hasRendered = true;
}
}

First, we extended the component. Next we attach a targeted listener in a life-cycle method. The “renderedCallback” method gives us access to the mounted elements.

Lets define some columns. We will give the first column a “fixedWidth”. According to the documentation, this option will enforce a set width.

// DatatablePlus.jsconst columns = [
     { label: '', fieldName: 'name', fixedWidth: 200 },
     { label: 'Col1', fieldName: 'Col1' },
     { label: 'Col2', fieldName: 'Col2' },
     { label: 'col3', fieldName: 'Col3' },
     { label: 'Col4', fieldName: 'Col4' },
];

Take a look at the result: Wasn’t that first column supposed to be a lot wider?

Extended Datatable w/ fixed width column.

What Happened?

That first column should be considerably wider than the others! It is instead displaying with the same width despite it’s “fixedWidth” setting!

It turns out that when extending an LWC, defining a life-cycle method overrides the parent’s implementation.

This means that whatever logic contained in the parent method does not run. If your extended component includes “connectedCallback”, say bye-bye to parent’s “connectedCallback”. In our example, our “renderedCallback” supersedes the original. For Lightning-Datatable, it turns out that some important column-width adjustments happen in “renderedCallback”. Our extension innocently wiped that functionality away.

A Super Solution

Luckily, there is a Super solution. We usually call “super” in a class constructor function. Here, we can use “super” as a namespace to access parent properties like life-cycle methods.

// DatatablePlus.js
renderedCallback() {
   
super.renderedCallback(); // Execute parent logic!

   
if (this._hasRendered) { return; }

   
const table = this.template.querySelector('tbody');
   table.addEventListener(
       'click',
       (e)
=> { console.log(e.target.tagName + ' was clicked.'); }
   );
       
   
this._hasRendered = true;
}

This pattern ensures the parent logic runs first, followed by our custom logic. Check out the updated result.

Extended Datatable w/ fixed width column.

This will work for any of the life-cycle methods. For instance, if you override “connectedCallback”, since Lightning-Datatable uses that method as well, we must call super.connectedCallback to maintain base functionality. Be warned, this is not covered in Salesforce component documentation at the time of this writing.

Equipped to Succeed

You are now equipped with some deep knowledge, have fun building extended LWCs! If you’d like an assist, or have another Salesforce development project in mind, then give us a shout. We’d be happy to help!

Protect Your Org.
Secure Your Data.

Salesforce security is a shared responsibility. Don't try to solve it alone.