How to implement a loading icon?

I would like to implement a loader ( But could not get it work. Is this even possible?
I just added the CSS code into a MyCSS.css which I imported in the light.css. After that I added a value animation: lds-spinner under style.

Could anybody help me?

This probably won’t readily work in Perspective.
Depending on the exact nature of the CSS used, you may be able to author a matching style class, which you would then be able to use directly in a Perspective component.

However, if the CSS isn’t part of the supported definitions of a style class, you’ll have to use a theme to define your classes. But even after you’ve created the class(es) required, you won’t be able to actually apply it to arbitrary Perspective elements.

I have this working, but I’m still testing out how to make it easiest to use within the designer. The biggest problem I see with your current situation (and one of the reasons why it isn’t working yet) is because you’re using lds-spinner as an animation value when lds-spinner should be typed into style.classes, like so:

However, that still won’t work. If you look at the actual CSS in a session using the browser’s dev tools, you’ll see that psc- will be prepended to your style class lds-spinner.

To fix this, go back to your webdev resource (or MyCSS.css) and change every instance of lds-spinner to psc-lds-spinner.

HOWEVER, this still might not work. For instance, the markup that is given in the docs you included above looks something like this:

<div class="lds-spinner">

Those extra divs actually need to be there for the spinner to work. There is not Perspective component that has the structure. For instance, if you look at a basic Label component, here is the markup that’s associated with it:

<div data-component="ia.display.label" data-component-path="C.0:1" class="ia_labelComponent" style="display: flex; flex-direction: column; justify-content: center; flex: 0 1 32px;">

This is clearly a different structure, so your animation won’t work OR it won’t do what you want it to.

HOWEVERER, there is a way to do what you want to do, but it will require you create two WebDev resources. You create your HTML and CSS text resource and then you can use an Inline Frame component to embed your spinner or whatever loading animation you want into your view. Then you would have a binding that will show and hide the iframe depending on some state. For example, when a table is loading data (before is populated, which is an easy binding), you can set the iframe’s meta.visible property to true and then when all of the table is loaded, you can set the iframe to false. The animation will still be playing in the background, it just won’t be visible to the user. I don’t know what the performance issues with this approach might be…

If you need some help on getting this done, I can set up a project and demonstrate it for you…

EDIT: Just so you know I have it working:


I actually do this with an icon and a simple CSS animation in a theme

Icon Props:

path: ""
color: ""
basis: 25px

Icon style:

  "border": "solid 5px #cfd0d1",
  "borderBottomColor": "#1c87c9",
  "borderRadius": "50%",
  "width": "25px",
  "animation": "1.5s linear infinite spinner",
  "height": "25px"

Animation in theme:

@keyframes spinner {
    0% {transform: rotate(0deg);}
    100% {transform: rotate(360deg); }

Ta-Dah! (It is a lot smoother but the gif made it a bit choppier for some reason)
Screen Recording 2021-12-09 at 11.26.46 AM-2


Heck ya, @kgamble! I was only bringing up how one can accomplish using the library OP posted. There are, of course, other ways to add spinners and other animations.

That looks great @YF129701!
I will try your solution and give you feedback asap.
Thanks a lot!

Okey just tested those ideas and i will go for the solution of @kgamble.
Thanks for your answers.

1 Like

where do you use this icon? How can you tell if it is loading something?

I used the icon settings from above but instead of the Animation I used an Expression on the angle binding. The if statement just turns off the rotation when in the designer because there is a default message on that in parameter.

if({view.params.Message}='!This Message!',0,toFloat(right(toStr(now(10)),4),0)*360)