Databinding delayed

Hi,

not sure, if this is a bug: I’ve something like this in js:

showBusyImage.value=true;
doSomethingThatTakesVeryLong();
showBusyImage.value=false;

and in .ux:

<WhileTrue Value="{showIdleImage}" >
   . . . show something to indicate that the app is busy . . .

I can see in debug, that the variable is set correctly to true and false, but in .ux this is visible AFTER the long running function is finished. So the busy image is never shown. If I skip the resetting of the variable (so it is not set back to false) the busy image is shown. So the basic process works, just the changed value does not reach the ux.

This happens in preview. On device I could not test yet, as building for android fails. I’ll try on another machine later today.

Hi!

This is to be expected. The UI does not update in the middle of a JavaScript function call (transaction), that would lead to glitch frames as the UI would be in inconsistent states.

You shuold not be doing long running tasks in your root level JavaScript code. Instead, you can dispatch to do a background task using setTimeout:

showBusyImage.value = true;

setTimeout(function() {
    doSomethingThatTakesVeryLong();
    showBusyImage.value = false;
});

Makes sense :slight_smile:

In my case I import some large amount of data and add it to a database, but that will usually be done very seldom.

I changed the code as follows, still the loading image (rotating arrow) is visible after the long task is finished:

function importWords() {
  toggleLoadingCircle();  // Sets variable showImage to true
  setTimeout(function() {
     var data = bundle.readSync("assets/data/words_de.txt");
      words = data.split("\n");
      addWordsToDb();
    //     toggleLoadingCircle();  // This is commented out, to see something at all.
  });
}

Ok, it’s hard for me to debug this further without seeing more of the code. The approach I suggested should work. If it doesn’t, there must be something else wrong, and I need a full test case to debug.

I tested quite a lot, in the end I found a way which seems to work for me. The code sample 2 rows above still does not work, the observable is not passed to ux until the long task is finished. No clue, why.

What works:

UX:

<OnUserEvent Name="toggleLoadingCircle">
    <Toggle Target="toggleLoadingCircle"/>
</OnUserEvent>

<Panel ux:Name="loadingCirclePanel" Alignment="Top" Margin="0,50,0,0" >
    <Image ux:Name="loadingCircle" File="assets/icons/loading.png" Height="70" Opacity="0" />
</Panel>

<WhileTrue ux:Name="toggleLoadingCircle" >
    <Change loadingCircle.Opacity="1" Duration="0.3" Delay="0.2" DelayBack="0" DurationBack="0"/> 
    <Spin Target="loadingCircle" Frequency="1"/> 
</WhileTrue>

```

JS:

```uno
UserEvents.raise("toggleLoadingCircle");
setTimeout(function() {
   . . . long running task
});
UserEvents.raise("toggleLoadingCircle");

```