StartUp screen pattern in Canvas Apps
Before you continue reading the article, I would like to point out that it already assumes certain knowledge of Power Apps concepts.
There are currently several options in Canvas Apps to trigger certain logic when the application starts. We have
Screen.OnVisible. Beyond that, there are a few settings associated with these formulas. How to make sense of all this? 🤯 And how should the data be loaded when the app starts? Let’s take a look.
Imagine a simple request approval application. We have two user roles - approver and requester. Both roles need common data to be loaded when they run the application – a list of request types, application styling and navigation menu items. In addition, each role needs to be redirected to a different initial screen - the approver wants to see a list-view of their approvals and the requester wants to see a list-view of their requests. Related to this is the need for each to load different data when the application starts - the approver will load the requests that are pending his approval and the requester will load the requests he has created.
First, let’s look at the simplest part. Where to load screen-related data? The first option is
App.OnStart. In order to load the data only if the user has a certain role, a condition similar to this would have to be added.
It will work, of course, but once there are more roles in the application and more requests to load screen-related data,
App.OnStart will be very messy. Besides, data that is only related to one screen is stored in a global variable, that’s not right either.
Let’s try it another way. Let the data be loaded only in the
Screen.OnVisible formula for a specific screen. And instead of a global variable, let’s use a context variable so that the data is only available in the required scope.
Next, we will look at where to decide what screen the user should be redirected to. Previously, the
Navigate function in
App.OnStart was used. This is now impossible due to the ‘Enable Navigate function in App.OnStart’ setting, which is disabled as recommended. Instead, the
App.StartScreen property is available in which the following evaluation can be performed.
But here comes another problem, what if we want to store the user role in a variable for later use. This is not possible, because
App.StartScreen is not a behavioral formula, so we cannot use the
Set function. Neither can we set a variable in
App.OnStart and use it in
App.StartScreen doesn’t support global variables. Therefore, it is necessary to perform
LookUp twice, once to evaluate
App.StartScreen and once to store it in a variable. That doesn’t sound too good, does it? 🤨
Before I present the solution for the variables and
App.StartScreen, let’s take a look at how to retrieve data common to the entire application. Of course, this data should be stored in a global variable and we can use the
App.OnStart. Which would look like this.
It looks good, but if you need to load large amounts of data, there will be a problem. It will take users quite a long time to start the application (see ‘Time to first screen’ in the application analytics report). However, this can be solved by enabling the ‘Use non-blocking OnStart rule’ setting. What this does is that it will run
Screen.OnVisible formulas in parallel when the app starts. If the setting is turned off, it always waits for
App.OnStart to finish before it starts evaluating
Screen.OnVisible - this is when the ‘Time to first screen’ is increased.
It almost looks like the ‘Use non-blocking OnStart rule’ will save us, but we might run into another problem. Let’s go back to our approval app and extend it with user groups. We want the approver to be able to see requests from other approvers in their group (e.g. HR). The user group should be stored in a global variable, so it can be used in other places in the application. Let’s do the following.
Do you see the problem? 🤔
scr_Approvals.OnVisible depends on the
varCurrentUser variable that is set in
App.OnStart are evaluated in parallel, so we may have a situation where
scr_Approvals.OnVisible starts evaluating and
varCurrentUser doesn’t contain data yet.
To give you an idea, I am attaching my little experiment 🧪
Finally, we come to the StartUp screen pattern that aims to solve most of the mentioned problems. This pattern is based on omitting the
App.OnStart formula, thus reducing the ‘Time to first screen’ to a minimum. Instead, a new screen
scr_StartUp will be created, which will be set as
App.StartScreen. All common variables will be set in the
scr_StartUp.OnVisible formula. The advantage is that at this point the app is already loaded and even though the data is still loading, you can already show some part of the interface to the user. Once everything in
scr_StartUp.OnVisible has been processed user must be redirected to the actual application screen. Unfortunately, you cannot use the
Navigate function in
Screen.OnVisible either. So you have to do something else. Fortunately, members of the PowerApps community 💜 have already figured this out - just use
tim_StartUp, which has following configuration.
Also I would like to remind you that you can disable
App.OnStart property in the settings 💡
To make this pattern clearer I am attaching a diagram.
To make it easier for the user to work with the application, don’t forget to add indicators on
scr_StartUp that the data is still being loaded. Such as progress overlay.
Let’s quickly return to the problem with
App.StartScreen. This can be solved very easily using the StartUp screen pattern. Just modify the above code to the following. This allows us to use global variables when selecting the intial screen.
This design pattern therefore helps to solve the problem of loading data when the application starts. Let’s summarize its advantages:
- Application starts very quickly (minimizing the ‘Time to first screen’ )
- Better code layout - we no longer have
scr_Initial.OnVisible, but only
- Cleaner code - setting the global variables in
scr_StartUp.OnVisibleand everything else only on the specific screens
Finally, I would like to recommend that while creating a new application, start by implementing the StartUp screen pattern. This will make the work that would be required for later modifications easier. The exceptions, of course, are applications with only one screen.
A template using the StartUp screen pattern is available on this link.