How to Use Lightning Spinner in LWC

When building applications in Salesforce Lightning Web Components (LWC), user experience is everything. Imagine clicking a button and nothing happens for a few seconds. Confusing, right?

That’s where a Lightning Spinner comes in.

A spinner tells users:
“Hold on, something is happening in the background.”

In this guide, you’ll learn how to use Lightning Spinner in LWC, fetch Account records from Apex, and display them in a Lightning Datatable — all in a clean, professional way.

Let’s build it step by step.


What is a Lightning Spinner in LWC?

A spinner is a loading indicator that appears during:

  • Server-side data fetch (Apex calls)

  • Record save operations

  • File uploads/downloads

  • Long-running integrations

In Salesforce LWC, we use the built-in base component:

<lightning-spinner></lightning-spinner>

It improves:

  •  User experience

  •  Prevents multiple clicks

  •  Reduces confusion

  •  Makes your UI look professional


What We Are Building

In this example, we’ll create a simple LWC that:

  • Shows a “Load Accounts” button initially

  • Displays a spinner when clicked

  • Fetches 10 latest Account records from Apex

  • Keeps the spinner visible for a minimum time

  • Displays data inside Lightning Datatable

And yes — it only needs 3 files:

  1. Apex Class

  2. LWC HTML

  3. LWC JavaScript


Step 1: Create Apex Controller

First, create an Apex class called AccountController.

public with sharing class AccountController {
@AuraEnabled(cacheable=true)
public static List<Account> getAccounts() {
return [
SELECT Id, Name, Industry, Phone
FROM Account
ORDER BY CreatedDate DESC
LIMIT 10
];
}
}

Why This Matters

  • @AuraEnabled(cacheable=true) → Allows LWC to call Apex & enables caching

  • ORDER BY CreatedDate DESC → Fetch latest records first

  • LIMIT 10 → Keeps performance optimized

Deploy this class before moving ahead.


Step 2: Design the HTML Template

Now we structure the UI using conditional rendering.

<template>

<!– Spinner –>
<template if:true={isLoading}>
<lightning-spinner
alternative-text=“Loading Accounts”
size=“medium”>
</lightning-spinner>
</template>

<!– Content –>
<template if:false={isLoading}>

<!– Show Datatable if data exists –>
<template if:true={accounts.length}>
<lightning-datatable
key-field=“Id”
data={accounts}
columns={columns}>
</lightning-datatable>
</template>

<!– Otherwise show button –>
<template if:false={accounts.length}>
<lightning-button
label=“Load Accounts”
variant=“brand”
onclick={handleLoad}>
</lightning-button>
</template>

</template>

</template>

What’s Happening Here?

Only one of these will show at a time:

  • Spinner

  • Button

  • Datatable

That’s the power of if:true and if:false.


Step 3: JavaScript Controller Logic

Now let’s control the spinner timing and fetch data.

import { LightningElement, track } from ‘lwc’;
import getAccounts from ‘@salesforce/apex/AccountController.getAccounts’;

export default class AccountTableWithSpinner extends LightningElement {

@track isLoading = false;
@track accounts = [];

columns = [
{ label: ‘Name’, fieldName: ‘Name’ },
{ label: ‘Industry’, fieldName: ‘Industry’ },
{ label: ‘Phone’, fieldName: ‘Phone’ }
];

handleLoad() {

this.isLoading = true;

const spinnerMinTime = 13000;
const startTime = Date.now();

getAccounts()
.then(result => {
this.accounts = result;
})
.catch(error => {
console.error(‘Error fetching accounts’, error);
})
.finally(() => {

const elapsedTime = Date.now() startTime;
const remainingTime = spinnerMinTime elapsedTime;

setTimeout(() => {
this.isLoading = false;
}, remainingTime > 0 ? remainingTime : 0);

});
}
}


Why Use Imperative Apex Call Instead of @wire?

Using imperative call:

  • Gives full control over spinner timing

  • Allows custom UI logic

  • Executes only when button is clicked

Perfect for user-triggered actions.


Step 4: Expose Component in Meta File

<?xml version=”1.0″ encoding=”UTF-8″?>
<LightningComponentBundle xmlns=“http://soap.sforce.com/2006/04/metadata”>
<apiVersion>63.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__AppPage</target>
<target>lightning__RecordPage</target>
<target>lightning__HomePage</target>
</targets>
</LightningComponentBundle>

This makes your component available in:

  • App Page

  • Record Page

  • Home Page


 Deploy & Test

  1. Deploy Apex + LWC via SFDX

  2. Open Lightning App Builder

  3. Drag component to page

  4. Save & Activate

  5. Click Load Accounts

You’ll see:

✔ Button initially
✔ Spinner appears after click
✔ Data loads after 13 seconds
✔ Records displayed in datatable

Clean. Simple. Professional.


 Spinner Customization Options

You can control spinner behavior using:

<lightning-spinner
size=“small | medium | large”
variant=“brand | inverse | neutral”
alternative-text=“Loading…”>
</lightning-spinner>

Example:

<lightning-spinner size=“large” variant=“brand” alternative-text=“Processing…”></lightning-spinner>

Advanced Enhancements You Can Add

Want to level up? Try these:

  •  Add ShowToastEvent for error handling

  •  Add pagination for large datasets

  •  Add filter by Industry

  •  Create overlay to block background clicks

  •  Remove fixed spinner timing in production


Best Practices for Using Lightning Spinner in LWC

  • Don’t keep spinner too long unnecessarily

  • Always provide alternative-text for accessibility

  • Use overlay for critical operations

  • Avoid blocking UI unless required


Final Thoughts

Using a Lightning Spinner in LWC is a small implementation — but it creates a big impact on user experience.

By combining:

  • Conditional rendering

  • Imperative Apex calls

  • Controlled loading state

You can build responsive, user-friendly Salesforce applications.

Whether you’re loading records, calling APIs, or processing files — a spinner keeps your users informed and confident.

Start implementing this pattern in your projects and you’ll instantly see the difference in UI quality.

Leave a Comment

Your email address will not be published. Required fields are marked *