Trying to learn how to properly reuse code. Basics of a clock updating every second. Would like to reuse the JS code for different UI LWC but running into various issues
Basic structure
/lwc ......Account LWC .............HTML, JS, CSS, Meta ......Clock LWC (Service) .............JS
UI say for account. Maybe one for case or contact. This code would be repeated (currently)
UI Javascript
import {LightningElement, api, wire, track} from 'lwc';
import { getRecord } from 'lightning/uiRecordApi'
import { getFieldValue } from 'lightning/uiRecordApi';
import { Clock } from 'c/clock';
export default class AccountTzClock extends LightningElement {
timeIntervalInstance;
accountRecord;
@api recordId;
@wire(getRecord, { recordId: '$recordId', fields: ['Account.Name', 'Account.UTC_Offset_Minutes__c', 'Account.GoogleAPI_Exception_Message__c'] })
dataLoaded(result){
if(result.data){
this.accountRecord = result.data;
this.startClock();
}
}
startClock() {
let utcos = getFieldValue(this.accountRecord, 'Account.UTC_Offset_Minutes__c') | 0;
if(Clock.updateClock( this, utcos)) {
this.timeIntervalInstance = setInterval(Clock.updateClock(this, utcos), 1000)
}else{
//Do stuff
}
}
get errorMsg(){
return getFieldValue(this.accountRecord, 'Account.GoogleAPI_Exception_Message__c');
}
}
The LWC Service JS that I would like to reuse is the JS that actually updates the clock. I have gotten to the point where it works on load. Not sure if there is a better way to gain access to the template and this
other than passing in this
like I am.
The problem now is that I cannot get setInterval
to work. I get "bind must be called on a function" but I have tried to placed bind in every conceivable place to no avail. (Yea I am green)
Any suggestions on the best way to reuse this service class and be able to use setTimeout with access to this
from the caller to gain access to the callers properties and template?
Clock Service JS
const updateClock = (that, utcOffset) => {
if(that.errorMsg != null){
return false;
}
var date = new Date();
var h = date.getUTCHours(); // 0 - 23
var m = date.getUTCMinutes(); // 0 - 59
var s = date.getUTCSeconds(); // 0 - 59
var o = utcOffset;
var hAdj = o / 60;
var session = "AM";
//Local Hour
h = h + hAdj;
//Rollover code
if( h < 0){
h = 24 + h;
}else if( h > 23){
h = h - 24;
}
if(h >= 8 && h < 18){
that.clockBackgroundColor = 'slds-theme_success';
}else{
that.clockBackgroundColor = 'slds-theme_error';
}
if (h >= 12) {
h = h > 12 ? h - 12 : h;
session = "PM";
}
if (h == 0) { //Midnight
h = 12;
}
h = (h < 10) ? "0" + h : h;
m = (m < 10) ? "0" + m : m;
s = (s < 10) ? "0" + s : s;
var time = h + ":" + m + ":" + s + " " + session;
var clockEle = that.template.querySelector("div.clock");
if(clockEle){
clockEle.innerText = time;
}
return true;
}
const Clock = {
updateClock: updateClock
}
export {Clock}
I did come up with a way to make it work but honestly it feels all wrong. Surely there has be a better way to do this...
To make it work I added the line:
let uc = function(){Clock.updateClock(this,utcos);}.bind(this);
to the startClock
method and replace the places where I was calling Clock.updateClock
with uc
making it like this:
startClock() {
let utcos = getFieldValue(this.accountRecord, 'Account.UTC_Offset_Minutes__c') | 0;
let uc = function(){Clock.updateClock(this,utcos);}.bind(this);
if(uc) {
this.timeIntervalInstance = setInterval(uc, 1000)
}else{
//do stuff
}
}
UTC_Offset_Minutes__c
andGoogleAPI_Exception_Message__c
? – salesforce-sas Aug 28 '19 at 3:21