Power Apps Loading Spinners: Native Controls, Busy States and Safe Save Patterns

C
Collab365 TeamAuthorPublished Jun 29, 2022
1,418

At a Glance

Target Audience
Canvas app makers building reliable loading, refresh and save experiences
Problem Solved
Show accurate progress feedback while disabling repeated actions and clearing the busy state after success or failure.
Use Case
Implement native screen or operation spinners, an accessible blocking overlay and an optional Timer-driven icon.

A Power Apps loading spinner should tell the truth: work is in progress. It should not pretend an operation succeeded, conceal a slow formula, or leave the save button active underneath it.

For a new canvas app, start with the native Spinner modern control for an explicit operation, or a screen’s LoadingSpinner property while screen-level controls or data are loading. Use a boolean busy variable to show the indicator and disable the triggering action. A Timer, SVG or GIF can change the appearance, but it is not the reliability mechanism.

Pick the right loading pattern

Situation Start with
A screen is loading its child controls or data Screen LoadingSpinner and LoadingSpinnerColor
A Save, Refresh or Submit action is running Modern Spinner controlled by a busy variable
The user must not press controls during the operation Busy overlay plus disabled actions
Progress has a measurable total Determinate progress rather than an indefinite spinner
You need a custom rotating icon Timer plus icon, after the native options are tested
The app is slow because it retrieves too much data Fix queries and delegation; a prettier spinner is not the fix

Microsoft describes the modern Spinner control as a way to show a loading scenario while an action is in progress. Its documented properties include Label, AccessibleLabel, Appearance, LabelPosition, SpinnerSize and Visible.

Pattern 1: use the screen’s built-in LoadingSpinner

A canvas-app Screen control has:

  • LoadingSpinner: None, Controls or Data;
  • LoadingSpinnerColor: the spinner colour.

Microsoft says Controls or Data shows the spinner until child controls at the screen level are visible. Nested controls are not considered.

Use this for the screen’s initial rendering and data load. It is not a general flag for an arbitrary button operation, and it does not automatically disable every interactive control.

Set a colour with sufficient contrast and test the real screen. A screen that continually shows the loader may have a formula, connector or data-volume problem that needs diagnosis.

Pattern 2: use a busy variable for Save or Refresh

Suppose a button writes to a SharePoint list. Set a variable before the operation, handle the error, and reset it afterwards:

Set(varBusy, true);

IfError(
    Set(
        varSavedRequest,
        Patch(
            Requests,
            Defaults(Requests),
            {
                Title: txtTitle.Text,
                RequestedBy: User().Email
            }
        )
    );
    Notify("Request saved.", NotificationType.Success),
    Notify(
        "The request was not saved: " & FirstError.Message,
        NotificationType.Error
    )
);

Set(varBusy, false)

Set the Spinner’s Visible property to:

varBusy

Give it a useful label such as Saving request and set AccessibleLabel to the same meaning.

Set the Save button’s DisplayMode to:

If(varBusy, DisplayMode.Disabled, DisplayMode.Edit)

That disabled state—not the animation—prevents another press of that button. If other interactive controls can trigger the same write, disable them too or place a deliberate overlay above the entire interactive region.

IfError and FirstError let the app distinguish success from failure. Never show a success message outside the error-aware path if the write may have failed.

Build a blocking overlay without trapping the user

For a full-screen operation:

  1. Add a container sized to the parent screen.
  2. Give it a slightly opaque fill so that the busy state is obvious.
  3. Place the Spinner and a short status label inside it.
  4. Set the container’s Visible property to varBusy.
  5. Ensure it appears above the controls it must block.
  6. Give the Spinner an AccessibleLabel and keep the message specific: Loading orders, Saving inspection, not merely Please wait.

Do not keep the overlay indefinitely. Define an error path, and where cancellation is safe, provide it. If cancelling could leave a partially committed operation, explain the state instead of offering a false escape.

Pattern 3: rotate an icon with a Timer

If the native Spinner cannot meet a required visual style, a hidden Timer control can drive an icon’s rotation.

Example settings:

Timer.Duration = 1000
Timer.Repeat = true
Timer.Start = varBusy
Timer.Visible = false
Timer.Reset = !varBusy

For an icon with a Rotation property:

360 * (tmrBusy.Value / tmrBusy.Duration)

Show the icon and status label only while varBusy is true. Microsoft notes that timers run in Preview mode while you are authoring, so use Preview or the published app when testing.

This technique is optional. It adds another control and another state to maintain; it does not make the data operation faster or safer.

What about SVGs and animated GIFs?

Power Apps can display image assets, and an SVG can be useful for a crisp brand illustration. But copying arbitrary SVG, CSS or HTML generated by an AI tool into an HTML Text control creates a code-review and accessibility obligation.

Before using a custom animation:

  • inspect the entire asset or markup;
  • remove external references and scripts;
  • test it in every supported Power Apps player;
  • check contrast, motion and screen-reader behaviour;
  • provide visible status text;
  • confirm that your organization permits the technique;
  • retain a simple native fallback.

An animated GIF is not automatically “dead,” nor is an SVG automatically tiny or fast. Measure the actual media size and app behaviour. Prefer native controls because their behaviour is documented and their intent is clearer.

Make the operation faster, not merely prettier

A spinner is a waiting-state control. It is not a performance optimization.

Check:

  • whether galleries call connectors once per row;
  • whether App.OnStart loads data the first screen does not need;
  • whether a query is delegable;
  • whether media files are larger than necessary;
  • whether one control references another screen and forces it to load;
  • whether independent connector calls can safely run concurrently.

Power Apps limits nondelegable local processing to 500 records by default, configurable up to 2,000. Read the delegation guidance and test beyond that limit; a spinner cannot correct incomplete results.

Concurrent() can overlap independent connector or Dataverse calls. Do not put dependent operations in the same block, and do not use it blindly when the destination is already throttling.

Test failure paths deliberately

Run these tests before release:

  1. successful save;
  2. invalid or missing required data;
  3. user without permission;
  4. connector or data source unavailable;
  5. offline or interrupted network;
  6. rapid double-click or double-tap;
  7. navigation away during the operation;
  8. large data set beyond the delegation limit;
  9. keyboard and screen-reader use;
  10. phone, tablet and browser layouts you claim to support.

Verify that the busy state always clears, the user gets an accurate result, and a failed operation does not create a duplicate on retry.

Frequently asked questions

Does Power Apps have a native Spinner control?

Yes. The current modern Spinner control is documented for loading scenarios and includes label, accessible-label, appearance, position and size properties.

What is the difference between Spinner and LoadingSpinner?

Spinner is a visible modern control you can bind to your own busy state. LoadingSpinner is a Screen property that shows a loader while screen-level controls or data become visible.

Does showing a spinner prevent duplicate submissions?

No. Disable every action that can start the write, or use a blocking overlay, and make the back end or flow duplicate-safe where consequences matter.

Should I use a Timer, SVG or GIF?

Only when the native control does not meet a verified requirement. They change presentation, not operation handling. Review security, size, accessibility and player compatibility.

Why does my spinner never disappear?

The busy variable may not be reset on an error path, or the underlying formula may not finish. Add IfError, inspect the operation with Live monitor, and reset the state after both success and failure.

For more production-safe canvas-app patterns, join the Power Apps Builders Space. Bring the operation you are waiting for and its current error path, not just the animation.