
In this blog post, we will explore how to build an Analog Clock Lightning Web Component (LWC) for Salesforce CRM. This clock component will display the current time and update in real-time. We will also discuss how this component can be used in Salesforce flexi pages and potential performance issues to be aware of.
Introduction to the Analog Clock LWC
The Analog Clock LWC is a visual component that uses SVG (Scalable Vector Graphics) to create a clock face with hour numbers, minute dots, and clock hands (hour, minute, and second). It will display the current time based on the system time, and the clock hands will rotate accordingly to show the time in an analog format.
Use Case: Case Management with Local Time Display
Imagine you are working with a multinational company that provides customer support and uses Salesforce for case management. The company’s customer support representatives handle cases from customers all around the world. It’s important for the support team to know the local time of the customer when interacting with them to ensure timely communication and support.
Creating the Analog Clock LWC
Let’s walk through the code and understand how the Analog Clock LWC is implemented:
The Template
The template contains an SVG element representing the clock face and its components. It uses LWC directives like for:each to loop through arrays of hour numbers and minute dots and renders them accordingly. The clock hands (hour, minute, and second) are represented by <line> elements, which are styled and rotated using CSS.
| <template> | |
| <div class="clock" > | |
| <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200"> | |
| <!-- Draw the clock face --> | |
| <circle class="clock-face" cx="100" cy="100" r="90" /> | |
| <!-- Draw the hour numbers --> | |
| <template for:each={hours} for:item="hour"> | |
| <text key={hour} class="hour-number" x={hour.cx} y={hour.cy}>{hour.value}</text> | |
| </template> | |
| <!-- Draw dots for the minutes --> | |
| <template for:each={dots} for:item="dot"> | |
| <circle key={dot} class="minute-dot" cx={dot.cx} cy={dot.cy} r="3" /> | |
| </template> | |
| <!-- Draw the clock hands --> | |
| <line class="hour-hand" x1="100" y1="100" x2="100" y2="70" /> | |
| <line class="minute-hand" x1="100" y1="100" x2="100" y2="60" /> | |
| <line class="second-hand" x1="100" y1="100" x2="100" y2="50" /> | |
| </svg> | |
| </div> | |
| </template> |
The JavaScript Controller
The JavaScript controller handles the logic of updating the clock in real-time. It uses the connectedCallback() lifecycle hook to start updating the clock immediately after the component is connected to the DOM. Additionally, it uses the setInterval() function to update the clock every second (1000 milliseconds).
The controller has two getters, hours and dots, which generate the positions of hour numbers and minute dots, respectively. These positions are calculated based on the clock’s radius and angles.
The updateClock() method is responsible for updating the clock hands’ angles based on the current time. The setHandRotation() method applies the rotation to the clock hands using the CSS transform property.
| import { LightningElement, api } from 'lwc'; | |
| export default class AnalogClock extends LightningElement { | |
| @api contactAddress; | |
| connectedCallback() { | |
| this.updateClock(); | |
| setInterval(() => { | |
| this.updateClock(); | |
| }, 1000); | |
| } | |
| renderedCallback() { | |
| this.updateClock(); | |
| } | |
| get hours() { | |
| // Generate hour numbers and their positions | |
| const hourNumbers = []; | |
| for (let i = 1; i <= 12; i++) { | |
| const angle = (i * 360 / 12) - 90; | |
| const cx = 100 + 75 * Math.cos(angle * Math.PI / 180); | |
| const cy = 100 + 75 * Math.sin(angle * Math.PI / 180); | |
| hourNumbers.push({ value: i, cx, cy }); | |
| } | |
| return hourNumbers; | |
| } | |
| get dots() { | |
| // Generate dots for the minutes and their positions | |
| const minuteDots = []; | |
| for (let i = 0; i < 60; i++) { | |
| if (i % 5 !== 0) { | |
| const angle = (i * 360 / 60) - 90; | |
| const cx = 100 + 85 * Math.cos(angle * Math.PI / 180); | |
| const cy = 100 + 85 * Math.sin(angle * Math.PI / 180); | |
| minuteDots.push({ cx, cy }); | |
| } | |
| } | |
| return minuteDots; | |
| } | |
| updateClock() { | |
| const now = new Date(); | |
| // Adjust the time based on the contact's address timezone or location information | |
| // You can use a library like Luxon or Moment.js to handle time zone conversions | |
| const hours = now.getHours(); | |
| const minutes = now.getMinutes(); | |
| const seconds = now.getSeconds(); | |
| // Calculate angles for the clock hands | |
| const hourAngle = (hours % 12 + minutes / 60) * 360 / 12; | |
| const minuteAngle = (minutes + seconds / 60) * 360 / 60; | |
| const secondAngle = seconds * 360 / 60; | |
| // Apply the rotation to the clock hands | |
| this.setHandRotation('hour-hand', hourAngle); | |
| this.setHandRotation('minute-hand', minuteAngle); | |
| this.setHandRotation('second-hand', secondAngle); | |
| } | |
| setHandRotation(handClass, angle) { | |
| const handElement = this.template.querySelector('.' + handClass); | |
| if (handElement) { | |
| handElement.style.transform = `rotate(${angle}deg)`; | |
| } | |
| } | |
| } |
The CSS Styling
The CSS styling defines the appearance of the clock and its components. The .clock-face represents the clock’s outer circle, and the .hour-number represents the hour numbers on the clock face. The .minute-dot represents the minute dots between the hour numbers. The .hour-hand, .minute-hand, and .second-hand represent the clock hands. The :host selector sets the size of the component.
| :host { | |
| display: block; | |
| width: 200px; /* Adjust the size as needed */ | |
| height: 200px; /* Adjust the size as needed */ | |
| } | |
| .clock { | |
| position: relative; | |
| width: 200%; | |
| height: 100%; | |
| } | |
| .clock-face { | |
| fill: #f0f0f0; | |
| stroke: #333; | |
| stroke-width: 2; | |
| } | |
| .hour-number { | |
| font-size: 14px; /* Increase font size for better visibility */ | |
| fill: #333; | |
| text-anchor: middle; | |
| dominant-baseline: middle; /* Center the text vertically */ | |
| } | |
| .minute-dot { | |
| fill: #333; | |
| } | |
| .hour-hand, | |
| .minute-hand, | |
| .second-hand { | |
| stroke: #333; | |
| stroke-width: 2; | |
| stroke-linecap: round; | |
| transform-origin: 50% 50%; | |
| } |
To use the Analog Clock LWC in Salesforce CRM, follow these steps:
- Create a new Lightning Web Component in your Salesforce org.
- Copy and paste the provided code into the LWC’s files (HTML, JS, and CSS).
- Deploy the LWC to your Salesforce org.
- Now, you can add the Analog Clock LWC to any Salesforce record page by dragging and dropping it from the Lightning App Builder.
Time Zone Handling: The clock currently displays the system time without considering the contact’s time zone. If you plan to use this component in a global context, consider getting the timezone based on an address. You can use the Google Maps Geocoding API to obtain the geographical coordinates (latitude and longitude) of the address, and then use those coordinates with a service like the Google Maps Time Zone API to get the timezone information.
| async getTimezone() { | |
| try { | |
| const geocodingApiKey = 'YOUR_GOOGLE_GEOCODING_API_KEY'; | |
| const timezoneApiKey = 'YOUR_GOOGLE_TIMEZONE_API_KEY'; | |
| // Step 1: Get coordinates (latitude and longitude) from the address using the Geocoding API | |
| const geocodingUrl = `https://maps.googleapis.com/maps/api/geocode/json?address=${encodeURIComponent( | |
| this.address | |
| )}&key=${geocodingApiKey}`; | |
| const geocodingResponse = await fetch(geocodingUrl); | |
| const geocodingData = await geocodingResponse.json(); | |
| if (geocodingData.results.length > 0) { | |
| const { lat, lng } = geocodingData.results[0].geometry.location; | |
| // Step 2: Get timezone information using the Time Zone API | |
| const timezoneUrl = `https://maps.googleapis.com/maps/api/timezone/json?location=${lat},${lng}×tamp=${Math.floor( | |
| Date.now() / 1000 | |
| )}&key=${timezoneApiKey}`; | |
| const timezoneResponse = await fetch(timezoneUrl); | |
| const timezoneData = await timezoneResponse.json(); | |
| if (timezoneData.timeZoneId) { | |
| // Step 3: Use Luxon to handle timezone conversions | |
| this.timezone = timezoneData.timeZoneId; | |
| // You can use the timezone with Luxon to convert dates and times as needed. | |
| } else { | |
| this.timezone = 'Timezone data not available'; | |
| } | |
| } else { | |
| this.timezone = 'Invalid address'; | |
| } | |
| } catch (error) { | |
| this.timezone = 'Error fetching timezone'; | |
| console.error(error); | |
| } | |
| } |
Once you get the timezone, get the time:
| function getCurrentTimeInTimezone(timezone) { | |
| const now = new Date(); | |
| const options = { timeZone: timezone, hour12: false, hour: 'numeric', minute: 'numeric', second: 'numeric' }; | |
| const formatter = new Intl.DateTimeFormat('en-US', options); | |
| const parts = formatter.formatToParts(now); | |
| // Extract the time components and format the time string | |
| const hour = parts.find(part => part.type === 'hour').value; | |
| const minute = parts.find(part => part.type === 'minute').value; | |
| const second = parts.find(part => part.type === 'second').value; | |
| const currentTimeInTimezone = `${hour}:${minute}:${second}`; | |
| return currentTimeInTimezone; | |
| } | |
| const timezone = 'America/New_York'; // Replace this with the desired timezone | |
| const currentTimeInTimezone = getCurrentTimeInTimezone(timezone); | |
| console.log(currentTimeInTimezone); // Output will be the current time in the specified timezone (e.g., "17:30:45") |
Potential Performance Issues : While the Analog Clock LWC provides a visually appealing way to display the time, it’s essential to be cautious of potential performance issues, especially when used in complex flexi pages with multiple components.
Frequent Updates: The clock is updated every second using setInterval(). Frequent updates can cause performance overhead, especially if there are other resource-intensive components on the page. Consider optimizing the update frequency based on your use case.
To mitigate performance issues, optimize the update frequency based on the use case (e.g., updating every minute instead of every second).
Conclusion
In conclusion, the Analog Clock Lightning Web Component (LWC) offers a captivating way to enhance your Salesforce CRM experience. Through the exploration of its creation and application, we’ve seen how this component can serve as a valuable addition to your Salesforce Flexi Pages. By seamlessly displaying the current time and updating in real-time, it addresses the need for local time awareness in a global context, particularly in scenarios like case management.
We delved into the details of building the Analog Clock LWC, breaking down its template, JavaScript controller, and CSS styling. The intricate dance of SVG elements and CSS transformations brings life to the clock face and its hands, showcasing the passage of time in an analog format. The JavaScript controller masterfully orchestrates the real-time updates, synchronizing the clock’s movements with the passing seconds.
As with any implementation, it’s crucial to consider potential performance issues. Frequent updates, while crucial for maintaining the real-time accuracy of the clock, can introduce overhead, especially when combined with other resource-intensive components. By carefully assessing your use case and optimizing the update frequency accordingly, you can strike a balance between functionality and performance.
Furthermore, we touched upon the importance of time zone handling, highlighting the current limitation of displaying the system time without considering the contact’s time zone. For a more comprehensive solution in a global context, we suggested leveraging external APIs like Google Maps Geocoding and Time Zone APIs to accurately present local times across various regions.
In your journey to enhance user engagement and interaction within your Salesforce CRM, the Analog Clock LWC stands as a prime example of the creative potential offered by Lightning Web Components. By understanding its inner workings, accounting for potential performance bottlenecks, and integrating time zone awareness, you can harness the power of this component to create visually stunning and functionally robust experiences.
So, whether you’re embarking on a mission to equip your customer support representatives with timely insights or simply looking to infuse a touch of elegance into your Salesforce Flexi Pages, the Analog Clock LWC is a versatile tool at your disposal. Embrace the art of timekeeping in its classic form, and watch as your Salesforce CRM becomes more dynamic, engaging, and seamlessly synchronized with the world around it.
About the blog
SFDCLessons is a blog where you can find various Salesforce tutorials and tips that we have written to help beginners and experienced developers alike. we also share my experience and knowledge on Salesforce best practices, troubleshooting, and optimization. Don’t forget to follow us on:
Newsletter
Subscribe to our email newsletter to be notified when a new post is published.

[…] Recommended Read: Create an Analog Clock Lightning Web Component in Your Salesforce Org […]