Skip to main content

Progress Indicator with Tabular Data

Headshot of article author Denise Moran

Progress indicators (also known as progress trackers) provide a great visual indication of how far along a user is to completion of a particular task. They set expectations of what’s to come so the user never feels lost or confused when using your app. When a user knows exactly where they are within a lengthy process they are less likely to abandon and complete the task.


Adding a progress indicator makes for a great user experience because they break down an overwhelming amount of information into easy to consume chunks. This post will explain when to use and how to create a progress indicator as well as provide an example to download for reuse.

A common business scenario where a progress indicator is of great use is a Sign-in app. Let’s imagine a company named Contoso wants to free up the time of a front desk admin who spends a wearisome amount of time signing guests in… typically there can be a long back and forth with the visitor and admin about the spelling of the guest’s name, “Was that Veronika with a K or Veronica with a C?”. Or perhaps multiple requests to re-take their picture because their eyes were closed. This can end up taking more time than needed which makes an application built on PowerApps an amazingly efficient solution.

The Sign-in application within this blog post breaks down the process into 4 chunks that are displayed with the assistance of a progress indicator:

  1. Complete form
  2. Take picture
  3. Confirm picture
  4. Agree to terms

You may be asking yourself, “Why was the information broken down like that?”. I could have easily displayed everything within one scrolling screen and accomplished the same thing, right?

Well, not exactly… Many users will abandon a form if it is too lengthy or indirect; this is why progress indicators are advised. The indicator enables the end user to know exactly where they are at within a step-by-step process. It provides expectations to the end user so that they know exactly where they are and how many steps they have left – no guessing or assuming anything.


Example: Contoso Sign-in Form


Break-down of information

I broke down the information by dividing the screens into tasks that the user must accomplish to reach their end goal (the goal being to complete the sign-in process to enter the building).

Note: on the Complete Form screen (displayed above), the user is only prompted to fill out a form and provide a signature. I could have allowed the user to agree to the terms and conditions at the same time, however I chose not to do that because this screen is dedicated to filling out a form – not reviewing documents.

By separating the information into different screens, I am focusing the user’s attention on a single task. I want the user to fully understand what they agreeing to and by dedicating an entire screen to that task I am communicating to the end user that this is an important task that they should focus their attention on.

The progress indicator, shown in the image below, also serves as a visual indication of where the user is at within the sign-in process.

Note: the colored green circle with label control underneath saying, “COMPLETE FORM” in a Semibold FontWeight. You may have noticed all of the other circles are colored gray with a FontWeight of Normal. These visual cues all help the user understand that they have 4 steps in total.

The user can clearly understand that they are currently on the COMPLETE FORM step and know they need to complete three more steps to finish the sign-in process.



The next step prompts the user to take their picture, note the progress indicator’s appearance has changed. The COMPLETE FORM circle and text has changed color to a dull green along with the FontWeight revised back to normal. These visual changes alert the user that the tasks within that previous screen is complete and lets the user know they currently on a different screen accomplishing a different task. That task being to take a picture to continue the sign-in process.

The take picture step has been separated from the confirm picture step in an effort to simplify the process. Separating the two screens allows the user to focus on taking the picture – the OnSelect of the camera preview will capture the image and the application will automatically navigate the user to the next screen so they may confirm the picture.



If the user is unsatisfied with the picture they may press the back button and retake their picture. However, if they are satisfied with their picture they may proceed by pressing the Next button.

Once the user has completed all of the steps, they are brought to another screen that prompts them to agree to the terms and conditions of that particular company. They user presses on the checkbox to confirm they have read through everything and can press Agree to finish up the sign-in process.



The user will then be prompted with a dialog that lets the user know they have completed the sign-in process.




The following section will explain how to design the tabular data and controls that visualize state of the progress indicator.

Controlled status color table

To create this visual appearance of the progress indicators, use tabular data (a Collection with multiple columns) to control the visual properties of the progress indicator. To do this, define the circle states: “Not started”, “In progress”, and “Complete”, in a Collection named “StatusColors”.

With this table, the controls we use to display the progress only need to look up values in this table based on status values we will define. This makes design changes later on easier, because you only need to make changes to this table and not each individual control property.


ClearCollect(StatusColors, {
     Status:"Not started",
     Fill: RGBA(166, 166, 166, 1),
     BorderColor: RGBA(205, 205, 205, 1),
     Color: RGBA(166, 166, 166, 1)
}, {
     Status:"In progress",
     Fill: RGBA(182, 221, 190, 1),
     BorderColor: RGBA(123, 183, 135, 1),
     Color: RGBA(123, 183, 135, 1)
}, {
     Fill: RGBA(85, 199, 112, 1),
     BorderColor: RGBA(11, 142, 30, 1),
     Color: RGBA(11, 142, 30, 1)


Note: This collection is defined in the OnStart property, which means it will be initialized before the user can see any of the screens.


Form status table

The state of each page of the form is stored in a Collection as well. This means that the competition state of a page can generate visuals set to specific controls, and the visuals are determined by matching the page’s status to the Status field we defined in the StatusColors Collection. The blank form Collection, called “FormPageStatus”, is also generated in the OnStart property of the application, and is defined below



     {Page: 1, Screen: VisitorSignIn, Name: "COMPLETE FORM", Icon: CompleteFormIcon, Status: "Not started"},
     {Page: 2, Screen: TakePicture, Name:" TAKE PICTURE", Icon: CameraIcon, Status: "Not started"},
     {Page: 3, Screen: ConfirmPicture, Name: "CONFIRM PICTURE", Icon: SmileyIcon, Status: "Not started"},
     {Page: 4, Screen: AgreeToTerms, Name: "AGREE TO TERMS", Icon: AgreementIcon, Status: "Not started"}

Note: the values in the Icon attribute are the names of media assets we have uploaded to the example PowerApp.

Designing the progress indicator control

Display the collection in a gallery. Insert a new blank horizontal gallery into the screen.


Select the gallery and set the Items property of the gallery to FormPageStatus. You can edit the data source of a gallery by clicking on the purple value of the “Data” option in the right-hand “Properties” panel.



Click into the gallery template (the first box) and insert a label. The Text property of the label should automatically change to the Name field (or ThisItem.Name), which we decided represents the name of the form stage.



The gallery will display the status of the form stages with color. Insert a circle icon into the gallery template and change the Fill property to: LookUp(StatusColors, Status=ThisItem.Status).Fill . Change the BorderColor property of the circle to LookUp(StatusColors, Status=ThisItem.Status).BorderColor .



We can indicate which screen the user is on by changing the font weight to bold, based on the App.ActiveScreen value: If(ThisItem.Screen = App.ActiveScreen, Bold, Normal)



To provide a visual for each stage, we have Icon as an attribute in the FormPageStatus collection. Here we added an Image control and set the Image property to ThisItem.Icon:


Once the gallery is formatted, copy and paste the gallery to each screen where you want to display the status. In this example, the progress indicator is displayed on all screens. Make sure the X and Y values of the progress indicator gallery are the same for each copy, otherwise it will appear to jump around the screen between pages.


Updating the form status

Now that we have the data and controls to display the status set up, we need to write actions that indicate when the status should be updated. For example, when you enter a screen in the form where the status was set to “Not started”, it needs to update the status to “In Progress”. Here is what we put on the OnVisible property of every screen:


Here is what is happening in this set of statements:

  1. The Set() function set the global variable CurrentPage to the record in our collection FormPageStatus that matches the active page. Saving the current page’s record into a variable makes it easier to access that record in the data set, which is done in the second statement.
  2. If the Status attribute of the CurrentPage variable is not equal to “Complete”, the status will get updated to “In Progress”. This lets the user see that they have visited a page but not completed that part of the form. If the part of the form was already completed, then the status will remain complete.
  3. In the Patch() statement, the first argument is the data source (the collection called FormPageStatus). The second argument is a reference to the record in curly brackets. The final argument in curly brackets is the updated value for the Status attribute.

To change the status to complete, the operation is the same except the status value is changed to “Complete”:


You would place this statement on some event that would signify that the form step is done. For example, you might want to place it on a “Next” button, and after the status changes you can navigate to the next screen in the form process.


In this example shown above, we have an If() statement that validates the form fields are filled out correctly. If they are, then the Patch() statement runs to change the first page’s status to complete. Finally, the application navigates to the next screen (in this case, to the screen TakePicture).

On the next page, the status of the first screen (COMPLETE FORM) turns to a dark green color, in contrast to the pale green color of the current page’s status (TAKE PICTURE). Recall that all we needed to do was copy and paste the gallery to each page, and the visuals are updated with the Patch statements. Since each gallery is simply reading from the same global data source (FormPageStatus), all we need to do now is indicate when and where the status should be updated. The controls and code needed to modify the visuals are all the same.

From here, all that is needed is to place the update statements in the appropriate action properties. At the end of the form you might want to refresh all the data if it’s a kiosk type app that will need to be re-used in the same session. You can do that by using the same ClearCollect() statement you used to initialize the FormPageStatus in the OnStart property of the application.



Download an export of this template here.