How-To: Events
As XMLUI runs events asynchronously, you cannot be sure when the event handler has completed. There are several situations when you should know whether an event handler is still in progress or you must do something after it has been completed.
In this article, you will learn how to manage a few typical situations related to event handlers.
Test if an event is in progress
In the following example, a button's click event handler runs for 3 seconds. Nonetheless, you can click the button several times before the 3 seconds expires:
<App var.logClick="">
<Button label="I'm running for 3 seconds, click me!"
onClick="
logClick += '+';
delay(3000);
" />
<Text>Clicks: {logClick}</Text>
</App>
Click the button several times quickly:
You can see that each click immediately logs a "+" sign. It means that multiple event handlers run simultaneously.
XMLUI has built-in support to check if a particular event handler is in progress. Each component supports an API property named <eventName>InProgress
set to true while the event handler runs.
The following sample demonstrates how you can use it. Here, the button is enabled only if the click event handler is not running:
<App var.logClick="">
<Button
id="myButton"
enabled="{!myButton.clickInProgress}"
label="I'm running for 3 seconds, click me!"
onClick="
logClick += '+';
delay(3000);
" />
<Text>Clicks: {logClick}</Text>
</App>
When you click the button, it remains disabled while the event handler runs, so you cannot start simultaneous click events.
Tracking event progress
Though the <event>InProgress
property (see here) helps check if an event handler is currently running, it does not allow reporting event progress.
For this purpose, you must use a variable tracking the progress as the following sample demonstrates:
<App var.phase="n/a">
<Button
id="myButton"
enabled="{!myButton.clickInProgress}"
label="I'm running a long operation, click me!"
onClick="
phase = 'Initializing';
delay(1000);
phase = 'Working';
delay(1000);
phase = 'Cleaning up';
delay(1000);
phase = 'Completed';
" />
<Text>Current phase: {phase}</Text>
</App>
Click the button and check how it reports progress:
Catching progress changes
You can combine the report progress mechanism with a ChangeListener
component to catch progress change events:
<App var.phase="n/a" var.logEntries="">
<ChangeListener
listenTo="{phase}"
onDidChange="() => logEntries += myButton.clickInProgress ? ' ' + phase : ''" />
<Button
id="myButton"
enabled="{!myButton.clickInProgress}"
label="I'm running a long operation, click me!"
onClick="
phase = 'Initializing';
delay(1000);
phase = 'Working';
delay(1000);
phase = 'Cleaning up';
delay(1000);
phase = 'Completed';
" />
<Text>Current phase: {phase}</Text>
<Text>Log: {logEntries}</Text>
</App>
The code collects progress phase changes in the logEntries
variable and displays them: