I have two almost identical Lightning Web Components with only difference that they use two different Apex Controller with two different Apex method to get data, the first component uses version with three parameters and the other component uses version with five parameters. I would like to follow the DRY principle (Don't Repeat Yourself) and to remove duplicate code for sorting datatable but I can't.
Documentation sounds very unclear how to implement that.
Listing of simpleTable.html
<template>
<template if:true={error}>
<template if:true={error.body}>
{error.body.message}
</template>
</template>
<lightning-datatable data={data} columns={columns} key-field="id" hide-checkbox-column
onsort={updateColumnSorting}></lightning-datatable>
</template>
Listing of simpleTable.js
import { LightningElement, track, api } from 'lwc';
import getColumnsAndData from '@salesforce/apex/SimpleTableCont.getColumnsAndData';
export default class SimpleTable extends LightningElement {
@api a;
@api b;
@api c;
@track data;
@track columns;
@track error;
//@track sortedBy;
//@track sortDirection;
connectedCallback() {
getColumnsAndData({a:this.a, b:this.b.split(','), c: this.c }).then(result=>{
this.data = result.data;
this.columns = result.columns;
}).catch(error => {
this.error = error;
});
}
// Client-side controller called by the onsort event handler
updateColumnSorting(e) {
//this.sortedBy = e.detail.fieldName;
//this.sortDirection = e.detail.sortDirection;
e.srcElement.sortedBy = e.detail.fieldName;
e.srcElement.sortDirection = e.detail.sortDirection;
this.sortData(e.detail.fieldName, e.detail.sortDirection);
}
sortData(fieldName, sortDirection) {
var reverse = sortDirection !== 'asc';
//sorts the rows based on the column header that's clicked
var data = this.data;
var primer = (data && data.length && data[0].Origin) ? (x, field)=>x.Origin[field] : null;
data.sort(this.sortBy(fieldName, reverse, primer))
this.data = JSON.parse(JSON.stringify(data)) ;
}
sortBy(field, reverse, primer) {
var key = primer ?
function(x) {return primer(x,field)} :
function(x) {return x[field]};
//checks if the two rows should switch places
reverse = !reverse ? 1 : -1;
return function (a, b) {
a = key(a);
b = key(b);
return reverse * ((a > b) - (b > a));
}
}
}
Listing of Table.html
<template>
<template if:true={error}>
<template if:true={error.body}>
{error.body.message}
</template>
</template>
<lightning-datatable data={data} columns={columns} key-field="id" hide-checkbox-column
onsort={updateColumnSorting}></lightning-datatable>
</template>
Listing of Table.js
import { LightningElement, track, api } from 'lwc';
import getColumnsAndData from '@salesforce/apex/TableCont.getColumnsAndData';
import {updateColumnSorting} from 'c/simpleTable';
import SimpleTable from 'c/simpleTable';
export default class DataTableLWC extends LightningElement {
@api a;
@api b;
@api c;
@api d;
@api e;
@track data;
@track columns;
@track error;
//@track sortedBy;
//@track sortDirection;
connectedCallback() {
getColumnsAndData({ a:this.a, b:this.b.split(',')
, c: this.c, d: JSON.parse(this.d.replace(/'/g, '"'))
, e: JSON.parse(this.e.replace(/'/g, '"')) })
.then(result=>{
this.data = result.data;
this.columns = result.columns;
}).catch(error => {
this.error = error;
});
}
updateColumnSorting(e) {
new SimpleTable().updateColumnSorting(e);
}
/*// Client-side controller called by the onsort event handler
updateColumnSorting(e) {
//this.sortedBy = e.detail.fieldName;
//this.sortDirection = e.detail.sortDirection;
e.srcElement.sortedBy = e.detail.fieldName;
e.srcElement.sortDirection = e.detail.sortDirection;
this.sortData(e.detail.fieldName, e.detail.sortDirection);
}
sortData(fieldName, sortDirection) {
var reverse = sortDirection !== 'asc';
//sorts the rows based on the column header that's clicked
var data = this.data;
data.sort(this.sortBy(fieldName, reverse));
this.data = JSON.parse(JSON.stringify(data)) ;
}
sortBy(field, reverse, primer) {
var key = primer ?
function(x) {return primer(x[field])} :
function(x) {return x[field]};
//checks if the two rows should switch places
reverse = !reverse ? 1 : -1;
return function (a, b) {
a = key(a);
b = key(b);
return reverse * ((a > b) - (b > a));
}
}*/
}
I would like to remove commented code from B.js
and reuse the same method from A.js
. However, both when I try to use
import {updateColumnSorting} from 'c/SimpleTable';
and
updateColumnSorting(e);
and when I try to use
import a from 'c/SimpleTable';
and
SimpleTable.updateColumnSorting(e);
I receive an error
Uncaught TypeError: SimpleTable.updateColumnSorting is not a function throws at /auraFW/javascript/pxtF0ZdGYF-z00XsmRUcGQ/aura_proddebug.js:6146:17
I even tried to add line
export * from SimpleTable;
to the end of SimpleTable.js file but it didn't compile.
How do I reuse Javascript code from one LWC in another LWC?
I tried to follow @muenzpraeger suggestion and try again to use suggestion from this article
import SimpleTable from 'c/SimpleTable';
updateColumnSorting(e) {
new SimpleTable().updateColumnSorting(e);
}
so I changed line
SimpleTable.updateColumnSorting(e);
to
new SimpleTable().updateColumnSorting(e);
However, it still throws me an exception
Uncaught ReferenceError throws at https://velocity-nosoftware-4149-dev-ed.lightning.force.com/auraFW/javascript/0Rz6fp7Oruhim-Qzw_AgRQ/aura_proddebug.js:8235:21
Looks like the problem is that I am unable to skip execution of parent constructor
of BaseLightningElement() which checks some local variable vmBeingConstructed
which I am not able to set or override at line 7195 of aura_proddebug.js
function BaseLightningElement() {
if (isNull(vmBeingConstructed)) {
throw new ReferenceError();
}
Looks like this complication is made intentional, there are some strange comments in the internal LWC code:
// interaction hooks
// We are intentionally hiding this argument from the formal API of LWCElement because
// we don't want folks to know about it just yet.
When I try to avoid execution of inherited constructor by defining a constructor at SimpleTable
constructor() {
//super();
}
which doesn't call super()
, I receive another error
Uncaught ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor throws at https://velocity-nosoftware-4149-dev-ed.lightning.force.com/auraFW/javascript/0Rz6fp7Oruhim-Qzw_AgRQ/aura_proddebug.js:8235:21