By following a tutorial (How to use custom LWC lightning component in lightning-datatable) I was able to extend lightning datatable and insert a button into the final column.
Now, I am currently struggling with how I communicate property changes down through the component hierarchy in order to disable/enable this button when certain events occur in the parent. I have checked the documentation regarding this (https://developer.salesforce.com/docs/component-library/documentation/lwc/lwc.create_components_data_binding) but I can't tailor the example to get a solution to my problem.
Below is the component that implements the custom datatable with a button in one column. When the button is pressed it disables itself and dispatches an event. This component listens for that dispatched event and after executing some action (omitted for brevity), I want to communicate to the button pressed (not all buttons) to enable itself once again.
I have experimented with declaring public properties on the button using @api, and then attempting to enable/disable the button using that, but all my efforts have been fruitless so I've omitted all attempts using that approach.
Here is my implementation:
customDatatableImplementation.html
<template>
<lightning-card title="Custom Datatable" icon-name="standard:contact">
<c-datatable-with-freeze-unfreeze-button
key-field="id"
data={data}
columns={columns}
onclick={handleToggleClick}
hide-checkbox-column>
</c-datatable-with-freeze-unfreeze-button>
</lightning-card>
</template>
customDatatableImplementation.js
import { LightningElement, track, api } from 'lwc';
export default class CustomDatatable extends LightningElement {
@api recordId;
@track columns = [];
@track data = [];
@track error;
@track toggleButtonLabel;
constructor() {
super();
this.template.addEventListener('changelabelevent', this.handleCustomEvent.bind(this));
}
handleToggleClick(event) {
if (this.toggleButtonLabel === 'Freeze') {
// Do something
// Communicate with button to enable itself again
}
else if(this.toggleButtonLabel === 'Unfreeze') {
// Do something
// Communicate with button to enable itself again
}
handleCustomEvent(event) {
const textVal = event.detail;
this.toggleButtonLabel = textVal;
}
}
My datatable that uses a custom type:
datatableWithFreezeUnfreezeButton.html
<template>
<c-datatable-with-freeze-unfreeze-button
key-field="id"
data={data}
columns={columns}
onclick={onclick}
hide-checkbox-column>
</c-datatable-with-freeze-unfreeze-button>
</template>
datatableWithFreezeUnfreezeButton.js
import LightningDatatable from 'lightning/datatable';
import freezeUnfreezeButton from './freezeUnfreezeButton.html';
export default class datatableWithFreezeUnfreezeButton extends LightningDatatable {
static customTypes = {
toggleButton: {
template: freezeUnfreezeButton
}
};
}
The button that is used to declare the custom type on my datatable and the one that dispatches an event up the hierarchy to customDatatableImplementation:
freezeUnfreezeButton.html
<template>
<lightning-button variant="neutral" label={toggleButtonLabel} title="Toggle content action"
onclick={handleToggleClick}>
</lightning-button>
</template>
freezeUnfreezeButton.js
import { LightningElement, track} from 'lwc';
export default class freezeUnfreezeButtonComponent extends LightningElement {
@track toggleButtonLabel = 'Freeze Card';
handleToggleClick() {
// Get the buttons label. We dispatch this to the tables
// controller in order to handle the correct event.
const selectEvent = new CustomEvent('changelabelevent', {
composed: true,
bubbles: true,
detail: this.toggleButtonLabel
});
// Change the label on the button
if (this.toggleButtonLabel === 'Freeze') {
this.toggleButtonLabel = 'Unfreeze';
} else {
this.toggleButtonLabel = 'Freeze';
}
// Dispatch the event to the parent
this.dispatchEvent(selectEvent);
}
}