Thursday, 9 September 2021

LWC: Share JavaScript code within a module & across your modules

 Introduction

One of the best practices while designing efficient lightning web component is to use utility javascript files to define the helper methods. This keeps the primary JavaScript file in your LWC module cleaner to read and debug. Most importantly to achieve reusability. In this blog, I would discuss & demonstrate the exporting-importing javascript functions.

Export within a module

Let's discuss this an example. Say I am developing a LWC module(homeComponent) in LWC to calculate certain maths equations. I need some functions to calculate difference between 2 numbers, products of 2 numbers etc. I received a JavaScript file(utility.js) from my fellow developer with these 2 methods defined. I just need to call those 2 methods in from my LWC.

Step 1 - would be to include the utility.js into my module homeComponent.


Step 2 should be exporting the functions in utility.js in order for homeComponent.js to consume it.

export {calculateDifference, calculateProduct};
function calculateDifference(val1, val2){
console.log('calculating difference in utility js');
return val1-val2;
}
function calculateProduct(val1, val2){
console.log('calculating product in utility js');
return val1*val2;
}
view raw utility v1.js hosted with ❤ by GitHub

Step 3 would be to import the functions in homeComponent.js and use them.

import { LightningElement } from 'lwc';
import { calculateDifference, calculateProduct } from './utility';
export default class HomeComponent extends LightningElement {
connectedCallback(){
console.log('diff is', calculateDifference(5,2));
console.log('product is', calculateProduct(5, 2));
}
}

When the connectedCallback is called, following would be printed in the browser console.


So, we have successfully imported two functions from our utility.js to our homeComponent.js file and used them.

This approach is called named export where we are specifying multiple functions to be exported.

Let me go one step further introduce another method in the utilty.js and make that as our exported method and keep the calculateDifference and calculateProduct methods as private methods. This way this I will only have to export one method and keep everything else in the utility.js as private.

export { calculate as default };
export function calculate(val1, val2, operation) {
if (operation == 'diff') {
return calculateDifference(val1, val2);
}
else if(operation == 'product'){
return calculateProduct(val1, val2);
}
}
function calculateDifference(val1, val2) {
//This is a private method now
console.log('calculating difference in utility js');
return val1 - val2;
}
function calculateProduct(val1, val2) {
//This is a private method now
console.log('calculating product in utility js');
return val1 * val2;
}
view raw utility v2.js hosted with ❤ by GitHub

Now importing the calculate function in similar way as previous one.

import { LightningElement } from 'lwc';
import { calculate } from './utility';
export default class HomeComponent extends LightningElement {
connectedCallback() {
console.log('product is ', calculate(5, 3, 'product'));
}
}
The browser log would look something like this now.


This approach is known as Export default, where we export only one function from a file. This is useful when there is only a single method to expose from a utility file. In case of multiple functions to export, named export is the way to go.

Export across modules

With this concept, I will briefly touch the approach of sharing JavaScript code across modules. This is widely used & more useful, however the concepts are same.

A good use case is displaying toast messages. In my projects, I refrain from invoking ShowToastEvent from each & every components, rather I keep a utility service component where I keep such reusable methods and call them whenever I require those functions.

My GlobalUtility.js would look like this

import { ShowToastEvent } from 'lightning/platformShowToastEvent';
export {showSuccessToast};
function showSuccessToast(self, msg) {
const evt = new ShowToastEvent({
title: 'Success',
message: msg,
variant: 'success',
});
self.dispatchEvent(evt);
}
Notice that I imported my required modules(lightning/platformShowToastEvent) in my utility, so I wont have to import them in my homeComponent, the actual consumer module.

import { LightningElement } from 'lwc';
import {showSuccessToast} from 'c/globalUtility';
export default class HomeComponent extends LightningElement {
connectedCallback() {
showSuccessToast(this, 'Successfully saved!');
}
}
The named export & export default approaches are also applicable in this global utility too.

Hope it helps! Thanks, have a good day.

LWC: Share JavaScript code within a module & across your modules

 Introduction One of the best practices while designing efficient lightning web component is to use utility javascript files to define the h...