1

I have a Lightning component that contains a table of retrieved data. The user can sort or filter the data in the table. Note that the data is on the client side in a list of Javascript objects and is NOT retrieved from apex when the user filters or sorts the data.

It mostly works well, however, if there is a very large amount of data in the table, the screen freezes during the sorting or filtering processes.

I'd like to provide some visual cue to the user to indicate that it is processing, but all the solutions for spinners or changing the mouse cursor presume there is a server side operation occurring. My sorting and filtering is all happening on the client side in JavaScript (i.e. in the controller and helper).

Any suggestions on how to provide a visual cue to the user that processing is occurring for a purely client side operation?

Thanks, Mike

1
  • Note that as a matter of practicality, a spinner would still be ideal, you would just need to write your sort algorithm in a way that can "break out" periodically to let the browser animate the spinner, but that involves calling setTimeout repeatedly during the middle of sorting, which means you wouldn't be able to use the native Array#sort method. I imagine you'd probably end up doing a custom selection sort or maybe even a merge sort.
    – sfdcfox
    Aug 7, 2018 at 19:11

2 Answers 2

3

Yes, you could use a CSS style for this.

CSS

.THIS.waiting {
  cursor: wait;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1000;
}

Then, for your component, you would set the waiting status:

$A.util.addClass(component.find("waitarea"), "waiting");
setTimeout($A.getCallback(function() { helper.doSort(component); }));

And then just remove the waiting class when you're done:

$A.util.removeClass(component.find("waitarea"), "waiting");

Note that a setTimeout is required to allow JavaScript to break back to the DOM long enough to apply the style, and the $A.getCallback is necessary to get back in to the Aura Life Cycle in order to update the state when doSort completes.

Your component would then start off as:

<aura:component ...>
  <div aura:id="waitarea"></div>

Example Code:


<aura:application >
    <ui:button label="Demo" press="{!c.press}" />
    <div aura:id="waiting"></div>
</aura:application>

({
    press: function(component, event, helper) {
        $A.util.addClass(component.find("waiting"), "wait");
        setTimeout($A.getCallback(function() {
            var i = 0;
            while(i++ < 1e5) {
                console.log(i);
            }
            $A.util.removeClass(component.find("waiting"), "wait");
        // Curiously, you do need a small (50ms) delay, maybe slightly longer
        // 50ms works on my browser (Chrome, Win 10 x64)
        }),50);
    }
})

.THIS.wait {
    position: fixed;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: 1000;
    cursor: wait;
}

Demo Spinner

11
  • Thanks for the suggestion, but this isn't quite getting me the effect I am looking for. If I remove the class in the main thread, it removes it before the sorting is complete - so quickly it never is even shown to the user. If I put it in the setTimeout method, the cursor is still not changed. Aug 7, 2018 at 20:06
  • @MikePaisner No, you remove the class in the doSort function (whatever you've called it), after sorting completes.
    – sfdcfox
    Aug 7, 2018 at 20:07
  • @MikePaisner You might be confusing sorting time with rendering time?
    – sfdcfox
    Aug 7, 2018 at 20:08
  • My sort function is like the following: displayList.sort(helper.myComparator); displayList is the variable with my list of objects. The myComparator contains logic for sorting: myComparator: function (a,b) { if a>b return -1; if a<b return 1; return 0; } Aug 7, 2018 at 20:11
  • @MikePaisner You need to have a function that does the sorting then removes the class afterwards. You need to set the waiting CSS class, setTimeout to give time for the browser to catch up, do the sort, then remove the CSS class at the end. You'll need to have enough records in the list for it to make a difference. Also, I think browsers only update onmousemove.
    – sfdcfox
    Aug 7, 2018 at 20:16
-1

FYI something similar was discussed at length here: $A.util.removeClass happens seconds after execution

Although it sounds like you are trying the same thing to no avail.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .