Equipment Request App with Approval Flows
Build a canvas app with Power Automate approval flows connected to Dataverse.
Introduction
30 Second Summary
Every company has employees who need new equipment. Laptops break, monitors fail, and teams grow. Without a system, these requests get lost in email threads and spreadsheets.
In this project, you will build a complete equipment request system using Microsoft Power Platform. Employees will submit requests through a custom app, managers will approve or reject them via email, and everyone can track the status in real time.
What You'll Build
An end-to-end equipment request system with a multi-screen canvas app for submitting and tracking requests, plus Power Automate cloud flows that handle approvals and cancellations behind the scenes.
By the end of this project, you'll have:
- Two custom Dataverse tables storing equipment categories and employee requests.
- A three-screen canvas app where employees browse equipment, submit requests, and track their status with live updates.
- An automated cloud flow that triggers on new requests, routes approval emails to a manager, and updates the status based on the outcome.
- An instant cloud flow callable directly from the app, letting employees withdraw pending requests with a single tap.
- Secret Mission: Add a try/catch error-handling pattern with scopes to the approval flow and create a scheduled flow that auto-escalates overdue requests.
Are there any prerequisites?
This project assumes you already have a Power Platform developer environment with a Dataverse database provisioned. If you completed Project 1 (the model-driven app project), you already have everything you need.
You should also be comfortable creating Dataverse tables and columns. This project builds on that foundation to focus on canvas apps and cloud flows.
Set Up Dataverse Tables
Every app needs a solid data foundation. Before you can build forms, galleries, or approval flows, you need tables in Dataverse that define the shape of your data.
In this step, you will create two custom tables: one for the equipment categories employees can request, and one for the requests themselves. You will also add sample data so your canvas app has something to display from the start.
In this step, get ready to:
- Create an Equipment Category table with text and currency columns.
- Create an Equipment Request table with text, lookup, choice, and multi-line text columns.
- Populate Equipment Category with sample rows.
Create the Equipment Category table
The Equipment Category table stores the types of equipment employees can request. Each category has a name, description, and unit cost.
- In the Power Apps maker portal, select Tables in the left navigation pane.
- On the command bar, select New table > Set advanced properties.
- In the right pane, enter Equipment Category as the Display name.
- Enter Categories of equipment available for employee requests as the Description.
- Select Save to create the table.
What is a Dataverse table?
A Dataverse table is like a spreadsheet in the cloud. Each table holds rows of data, and each column defines a field (like Name or Cost). Tables are the backbone of every Power Platform app.
Now add the custom columns this table needs. The primary column (named "Name" by default) will serve as your Category Name field.
- Open the Equipment Category table you just created.
- Select the Columns area.
- Select New column on the command bar.
- Set Display name to Description.
- Set Data type to Text.
- Select Save.
- Select New column again.
- Set Display name to Unit Cost.
- Set Data type to Currency.
- Select Save.
Why Currency instead of a plain number?
Currency columns automatically handle formatting, currency symbols, and precision. They also support multi-currency scenarios if your organization uses more than one currency.
Don't see the New column option?
Make sure you opened the table first, then navigated to the Columns area. The New column button appears on the command bar only when you are inside the Columns view.
Help me find the New column button in my table.
Create the Equipment Request table
The Equipment Request table stores each employee's request. It links to the Equipment Category table via a lookup column and uses a choice column for tracking status.
- Return to the Tables area in the left navigation.
- On the command bar, select New table > Set advanced properties.
- Set Display name to Equipment Request.
- Enter Employee equipment requests with approval tracking as the Description.
- Select Save to create the table.
Now add six custom columns to the Equipment Request table. The primary column ("Name") will serve as your Request Title.
- Open the Equipment Request table and select the Columns area.
- Select New column. Set Display name to Equipment Category and Data type to Lookup.
- In the Related table dropdown, select Equipment Category.
- Select Save.
What is a Lookup column?
A Lookup column creates a relationship between two tables. Instead of typing a category name into every request, the lookup lets employees pick from existing Equipment Category rows. This keeps data consistent and avoids typos.
- Select New column. Set Display name to Justification and Data type to Multiline Text.
- Select Save.
- Select New column. Set Display name to Status and Data type to Choice.
- Select View more, then select Local choice.
- Add four options: Submitted, Approved, Rejected, and Withdrawn. Use Add new item to add each additional option.
- Select Save.
What is a Choice column?
A Choice column provides a fixed dropdown list of values. This ensures every request has a valid status value. Your approval flow will update this column automatically when a manager approves or rejects a request.
- Select New column. Set Display name to Requested By and Data type to Text.
- Select Save.
- Select New column. Set Display name to Approver Email and Data type to Text.
- Select Save.
Your Equipment Request table now has all six columns: Request Title (primary), Equipment Category (Lookup), Justification (Multiline Text), Status (Choice), Requested By (Text), and Approver Email (Text).
Seeing an error when saving a column?
Double-check that the Display name does not match an existing system column name. Dataverse reserves some names like "Status" for its own system columns. If you see a conflict, try the display name Request Status instead and adjust references in later steps.
Help me resolve a column name conflict in Dataverse.
Populate Equipment Category with sample data
Your canvas app needs data to display. Adding sample rows now means you can test your gallery as soon as you build it in Step 2.
- Return to the Tables area and open the Equipment Category table.
- Select Edit on the command bar to open the table data editor.
- Add the following four rows by clicking into each cell and typing the values:
- Row 1: Name = Laptop, Description = Standard business laptop, Unit Cost = 1200.
- Row 2: Name = Monitor, Description = 27-inch external display, Unit Cost = 450.
- Row 3: Name = Headset, Description = Noise-cancelling USB headset, Unit Cost = 150.
- Row 4: Name = Docking Station, Description = USB-C docking station with dual display support, Unit Cost = 250.
After entering all four rows, confirm they appear in the data grid with the correct values.
Use Tab to move between cells
Press Tab to move from one cell to the next in the data editor. This speeds up data entry significantly.
Your data foundation is ready. Next up, you will build a canvas app with multiple screens that connect to these tables and let employees browse categories, submit requests, and track their status.
Build the Canvas App Screens
Your Dataverse tables are ready with columns and sample data. Now it is time to build the front end that employees will actually interact with.
In this step, you will create a canvas app with three screens: one for browsing available equipment, one for submitting a request, and one for tracking existing requests. Each screen connects directly to your Dataverse tables using Power Fx formulas.
In this step, get ready to:
- Create a blank tablet-layout canvas app inside the project solution.
- Build three screens with galleries and forms connected to Dataverse.
- Wire up navigation between screens using Navigate() and Back().
Create the canvas app and build the Browse Screen
A canvas app gives you full control over layout and design. You will start with a blank tablet-layout app so every screen is built from scratch.
- Switch back to the Power Apps maker portal at make.powerapps.com.
- Make sure your developer environment is selected in the top-right environment switcher.
- In the left navigation, select Solutions.
- Open the solution you created in the previous project (or create a new unmanaged solution for this project).
- Select + New at the top, then App, then Canvas app.
- Enter a name such as Equipment Request App.
- Select Tablet as the format.
- Select Create.
The Power Apps Studio opens with a blank screen called Screen1. This is your starting point.
Why a blank app instead of a template?
Templates auto-generate screens and formulas, but they hide the logic you need to understand for the PL-200 exam. Building from blank ensures you practice every gallery, form, and formula pattern yourself.
- Rename Screen1 to BrowseScreen by double-clicking its name in the left Tree view pane.
- Select the Insert tab at the top, then select Gallery, then Blank vertical.
- With the gallery selected, look at the Properties pane on the right. Set the Data source dropdown to Equipment Category.
What if I don't see my table in the dropdown?
Select See all tables or search for it by name. Your Dataverse tables appear automatically because the app is inside the same environment.
- Verify the formula bar shows the Items property. It should now display your table name. Confirm it reads:
'Equipment Category'
What does this formula do?
Setting Items to 'Equipment Category' tells the gallery to load every row from your Equipment Category table. The single quotes are required because the table name contains a space.
- Select the pencil icon (edit template) on the first gallery item.
- Insert a Label control inside the gallery template and set its Text property to:
ThisItem.'Category Name'
- Add a second Label below the first and set its Text property to:
ThisItem.Description
What does ThisItem mean?
Inside a gallery template, ThisItem refers to the current row being rendered. Each item in the gallery gets its own copy of the template, automatically populated with that row's data.
- Save the app by pressing Ctrl+S (Windows) or Cmd+S (macOS).
- Press the Play button (triangle icon in the top-right) to preview the app. You should see your four equipment categories (Laptop, Monitor, Headset, Docking Station) listed in the gallery.
Gallery is empty?
Check that your Equipment Category table has sample rows. Return to the Dataverse tables area and confirm the data exists.
Also confirm the Items property is set to 'Equipment Category' (with single quotes). A red error icon in the formula bar indicates a typo.
Why is my gallery not showing any data?
Build the Submit Screen with an Edit Form
Employees need a form to submit new equipment requests. An Edit Form control connects directly to a Dataverse table and handles record creation automatically when you call SubmitForm().
- Close the preview if it is still open by pressing the X in the top-right corner (or press Esc).
- Add a new screen by selecting New screen at the top, then Blank.
- Rename the new screen to SubmitScreen in the Tree view.
- With SubmitScreen selected, go to Insert and select Edit form.
- In the Properties pane on the right, set Data source to Equipment Request.
- Set Default mode to New in the Properties pane. This tells the form to create a new record (not edit an existing one).
- Select Edit fields in the Properties pane, then add these fields: Request Title, Equipment Category, Justification, Status, Requested By, and Approver Email.
Now you need to set default values for two fields so employees do not have to fill them in manually.
- In the Tree view, expand the form and find the Requested By card. Select the text input (DataCardValue) inside that card.
- In the formula bar, select the Default property from the property dropdown and set it to:
User().Email
- Find the Status card in the Tree view. Select the dropdown or text input (DataCardValue) inside that card.
- Set its Default property to:
"Submitted"
What do these defaults do?
User().Email returns the email address of whoever is currently signed in. This means the Requested By field auto-fills with the employee's identity.
Setting Status to "Submitted" ensures every new request starts in the correct state for the approval flow to pick up later.
- Add a Button control below the form (Insert > Button).
- Set the button's Text property to "Submit Request".
- Set the button's OnSelect property to:
SubmitForm(Form1)
What does SubmitForm do?
SubmitForm() takes all the values currently in the form and writes them as a new row to the connected Dataverse table. Because Default mode is set to New, each submission creates a new Equipment Request record.
- Save the app with Ctrl+S (Windows) or Cmd+S (macOS).
- Preview the app and navigate to SubmitScreen (use the Tree view dropdown at the top). Fill in the form fields and select Submit Request. Confirm a new row appears in your Equipment Request table by checking the Dataverse data workspace.
Form shows an error on submit?
Make sure all required fields have values. If the Equipment Category lookup is blank, select a category before submitting.
Also check that the form's DataSource property is set to 'Equipment Request' (the table name with single quotes).
Help me fix my Edit Form submit error in Power Apps.
Build the My Requests Screen and add navigation
Employees need to see only their own requests and check whether each one has been approved, rejected, or is still pending. A filtered gallery combined with conditional color formatting makes the status instantly visible.
- Add another new screen (New screen > Blank) and rename it to MyRequestsScreen.
- Insert a Blank vertical gallery on this screen.
- Select the gallery and set its Items property in the formula bar to:
Filter('Equipment Request', 'Requested By' = User().Email)
What does this formula do?
Filter() narrows the full Equipment Request table down to only rows where the Requested By column matches the current user's email. Each employee sees only their own requests.
- Select the gallery template (pencil icon) and insert a Label for the request title. Set its Text property to:
ThisItem.'Request Title'
- Add a second Label to display the status. Set its Text property to:
ThisItem.Status.Value
- With the status label still selected, set its Color property to the following formula for conditional formatting:
If(
ThisItem.Status.Value = "Approved", Color.Green,
ThisItem.Status.Value = "Rejected", Color.Red,
ThisItem.Status.Value = "Withdrawn", Color.Gray,
Color.DarkOrange
)
How does the conditional color work?
The chained If() function checks the Status value and returns a color accordingly. Approved shows green, Rejected shows red, Withdrawn shows gray, and anything else (Submitted) shows dark orange. This gives employees an instant visual signal.
Now connect the three screens with navigation so users can move between them.
- Switch to BrowseScreen in the Tree view.
- Add a Button control labeled "Submit Request". Set its OnSelect property to:
Navigate(SubmitScreen)
- Add another Button labeled "My Requests". Set its OnSelect property to:
Navigate(MyRequestsScreen)
- Switch to SubmitScreen and add a Back arrow icon (Insert > Icons > Back). Set its OnSelect property to:
Back()
- Switch to MyRequestsScreen and add a Back icon. Set its OnSelect to Back() as well.
Navigate vs Back
Navigate() takes the user to a specific screen by name. Back() returns to whichever screen they came from, like a browser back button. Use Navigate when you know the destination. Use Back for a generic return.
- Save the app with Ctrl+S (Windows) or Cmd+S (macOS).
- Preview the app. Select Submit Request on the Browse Screen to navigate to the form. Submit a test request, then use the back arrow to return. Select My Requests and confirm only your records appear with color-coded statuses.
Navigation buttons not working?
Confirm the screen names in your Navigate() formulas exactly match the names in your Tree view. Screen names are case-sensitive.
If the formula bar shows a red error underline, click on the error message to see what Power Apps expected.
My Navigate formula has an error in Power Apps. Help me fix it.
✔️ Awesome, I've got everything!
Great. Double check you have saved the app and all three screens are functional in preview mode.
ⓧ I'd like to double check the full setup
Here is a summary of all key formulas across the three screens:
// BrowseScreen
// Gallery Items property:
'Equipment Category'
// Gallery Label 1 Text:
ThisItem.'Category Name'
// Gallery Label 2 Text:
ThisItem.Description
// Submit Request Button OnSelect:
Navigate(SubmitScreen)
// My Requests Button OnSelect:
Navigate(MyRequestsScreen)
// SubmitScreen
// Edit Form DataSource: 'Equipment Request'
// Edit Form Default mode: New
// Requested By DataCardValue Default:
User().Email
// Status DataCardValue Default:
"Submitted"
// Submit Button OnSelect:
SubmitForm(Form1)
// Back Icon OnSelect:
Back()
// MyRequestsScreen
// Gallery Items property:
Filter('Equipment Request', 'Requested By' = User().Email)
// Request Title Label Text:
ThisItem.'Request Title'
// Status Label Text:
ThisItem.Status.Value
// Status Label Color:
If(
ThisItem.Status.Value = "Approved", Color.Green,
ThisItem.Status.Value = "Rejected", Color.Red,
ThisItem.Status.Value = "Withdrawn", Color.Gray,
Color.DarkOrange
)
// Back Icon OnSelect:
Back()
Your canvas app now has three working screens connected to Dataverse. Next up, you will add variables, error handling, and a refresh pattern to make the app production-ready.
Add Canvas App Logic and Error Handling
Your canvas app has three screens, but they operate in isolation right now. The Browse Screen shows equipment categories, and the Submit Screen has a form. But there is no connection telling the form which category the user selected.
In this step, you will wire the screens together using a variable, add error handling so the user gets a clear banner when something goes wrong, and use a local collection to keep the My Requests screen fast and up to date.
In this step, get ready to:
- Pass the selected equipment category to the Submit form using a variable.
- Add error handling around form submission with a Notify banner.
- Load requests into a local collection for faster screen loads.
Set a variable to pass the selected category
When a user taps a category in the Browse Gallery, the app needs to remember that choice and carry it over to the Submit Screen. A global variable is the simplest way to pass data between screens in a canvas app.
- In Power Apps Studio, expand the Tree view on the left and select the Browse Screen.
- Select the Gallery control that displays your equipment categories.
- In the property dropdown at the top left (next to the formula bar), select OnSelect.
- Replace the existing formula with the following:
// Store the selected category in a global variable, then navigate
Set(varSelectedCategory, ThisItem);
Navigate('Submit Screen')
What does this formula do?
Set(varSelectedCategory, ThisItem) creates a global variable called varSelectedCategory and stores the entire gallery row (the category record) inside it.
Navigate('Submit Screen') then takes the user to the Submit Screen. Because the variable is global, it is available on any screen in the app.
Now you need to tell the form to use this variable as the default value for the Equipment Category lookup field.
- Navigate to the Submit Screen in the Tree view.
- Expand the Edit Form control and find the Equipment Category data card.
- Select the data card, then click Advanced in the right-hand Properties pane.
- Click the lock icon to unlock the card so you can edit its properties.
- Select the DataCardValue control inside the Equipment Category card (this is the combo box or dropdown).
- Set its DefaultSelectedItems property to the following formula:
// Pre-fill the lookup with the category the user selected on the Browse Screen
If(!IsBlank(varSelectedCategory), [varSelectedCategory])
Why wrap it in If(!IsBlank(...))?
If the user navigates to the Submit Screen without selecting a category first (unlikely, but possible), varSelectedCategory would be blank. The If guard prevents the lookup control from showing a blank selection error.
- Press F5 (or click the Play button) to preview the app.
- Select any category in the Browse Gallery (for example, Laptop).
- Verify that the Submit Screen opens with the Equipment Category field pre-filled with your selection.
Category not pre-filling?
Make sure you unlocked the data card before editing the DefaultSelectedItems property. Locked cards ignore custom formulas.
Confirm that the variable name in Set() on the Browse Gallery matches the name you referenced in DefaultSelectedItems exactly (varSelectedCategory).
help me debug why my Equipment Category lookup is not pre-filling from the variable
Wrap form submission in error handling
Right now, if a user taps Submit and something goes wrong (a required field is blank, a network timeout occurs), the app fails silently. The IfError function lets you catch submission errors and show a user-friendly banner instead.
- On the Submit Screen, select your Submit button.
- In the property dropdown, select OnSelect.
- Replace the existing formula with:
// Attempt to submit the form; show an error banner if it fails
IfError(
SubmitForm(Form1),
Notify("Something went wrong. Please check all fields and try again.", NotificationType.Error)
)
What does IfError do here?
IfError evaluates the first argument (SubmitForm(Form1)). If the submission succeeds, execution continues normally. If it returns an error, IfError runs the second argument instead.
Notify() displays a red banner at the top of the screen with your message. The NotificationType.Error argument controls the color and icon. The banner auto-dismisses after 10 seconds.
Next, set up what happens after a successful submission. The form control has a built-in OnSuccess property that fires only when SubmitForm completes without error.
- Select the Form1 Edit Form control (not the button).
- In the property dropdown, select OnSuccess.
- Enter the following formula:
// After a successful save, refresh the data source so My Requests is up to date
Refresh('Equipment Request');
Navigate('My Requests Screen')
Why Refresh before Navigate?
Refresh('Equipment Request') tells Power Apps to re-read the latest data from Dataverse. Without it, the My Requests gallery might show stale cached data and the new submission would be missing.
Placing Refresh inside OnSuccess guarantees it only runs when the row was actually saved. If submission failed, the user stays on the form to fix the problem.
- Press F5 to preview the app.
- On the Submit Screen, leave a required field blank (for example, Request Title) and tap Submit.
- Verify that a red error banner appears at the top of the screen.
- Now fill in all fields and tap Submit again.
- Verify that the app navigates to the My Requests Screen.
Not seeing the error banner?
Confirm that formula-level error management is enabled. Go to Settings > Updates > Retired and make sure Disable formula-level error management is turned Off.
Also check that the form control name in your IfError formula matches the actual name shown in the Tree view. If your form is named Form1_1 instead of Form1, update the formula to match.
help me troubleshoot why my IfError Notify banner is not appearing when form submission fails
Load requests into a local collection
Every time the My Requests Screen becomes visible, it queries Dataverse directly. For a smoother experience and to guarantee the latest data shows up after submitting, you will load the data into a local collection using ClearCollect.
- In the Tree view, select the My Requests Screen (the screen itself, not a control on it).
- In the property dropdown, select OnVisible.
- Enter the following formula:
// Cache the current user's requests in a local collection each time this screen appears
ClearCollect(
colMyRequests,
Filter('Equipment Request', 'Requested By' = User().Email)
)
What is ClearCollect?
ClearCollect empties the collection first, then fills it with fresh data. This ensures you never see duplicates from a previous load.
Because this formula runs in OnVisible, it re-executes every time the user navigates to this screen. Combined with the Refresh you added in the previous substep, new submissions appear immediately.
Now point the gallery at the collection instead of hitting Dataverse directly.
- Select the Gallery control on the My Requests Screen.
- Set its Items property to:
colMyRequests
- Press F5 to preview the app.
- Browse a category, fill in the Submit form, and submit a request.
- Verify that the My Requests Screen loads and your new request appears in the gallery with a Status of Submitted.
Gallery showing no data?
Make sure the Gallery's Items property is set to colMyRequests (the collection), not the previous Filter(...) formula.
Check that the column name in your Filter matches exactly. Dataverse display names are case-sensitive in Power Fx. The correct column name is 'Requested By' (with the space and capital letters).
help me figure out why my My Requests gallery is empty after setting ClearCollect in OnVisible
✔️ Awesome, I've got everything!
Great. Double check you have saved your app (Ctrl+S or Cmd+S) before moving on.
ⓧ I'd like to double check the full code
Here is a summary of every formula you added or changed in this step:
// ===== Browse Screen =====
// Browse Gallery > OnSelect
Set(varSelectedCategory, ThisItem);
Navigate('Submit Screen')
// ===== Submit Screen =====
// Equipment Category DataCardValue > DefaultSelectedItems
If(!IsBlank(varSelectedCategory), [varSelectedCategory])
// Submit Button > OnSelect
IfError(
SubmitForm(Form1),
Notify("Something went wrong. Please check all fields and try again.", NotificationType.Error)
)
// Form1 > OnSuccess
Refresh('Equipment Request');
Navigate('My Requests Screen')
// ===== My Requests Screen =====
// Screen > OnVisible
ClearCollect(
colMyRequests,
Filter('Equipment Request', 'Requested By' = User().Email)
)
// My Requests Gallery > Items
colMyRequests
Your canvas app now passes data between screens, handles submission errors gracefully, and keeps the My Requests gallery fresh. Next up, you will build an automated cloud flow that sends an approval email every time a new equipment request lands in Dataverse.
Create the Automated Approval Flow
Your canvas app can submit equipment requests to Dataverse, but right now those requests just sit there. Nobody gets notified and no decision ever happens.
In this step, you will build an automated cloud flow in Power Automate that watches for new Equipment Request rows and routes each one through a formal approval process. When the approver responds, the flow updates the request status automatically.
In this step, get ready to:
- Create an automated cloud flow with the Dataverse trigger.
- Add an approval action and condition logic to route decisions.
- Test the full approval cycle from the canvas app.
Create the automated cloud flow and configure the trigger
An automated cloud flow runs whenever a specific event occurs. You need a flow that fires every time a new row lands in the Equipment Request table.
- Open a new browser tab and navigate to make.powerautomate.com.
- Confirm your developer environment is selected in the top-right environment switcher.
- In the left navigation, select Solutions.
- Select the solution you created for this project.
- Select New > Automation > Cloud flow > Automated.
- In the Flow name field, enter Equipment Request Approval.
- In the trigger search box, search for When a row is added and select the When a row is added, modified or deleted trigger under Microsoft Dataverse.
- Select Create.
The flow designer opens with the trigger card ready to configure.
- In the Change type dropdown, select Added.
- In the Table name dropdown, select Equipment Requests (your Equipment Request table).
- In the Scope dropdown, select Organization.
What does this trigger do?
The When a row is added, modified or deleted trigger watches your Dataverse table for changes. By setting Change type to Added, the flow only fires when a brand-new row appears. Organization scope means it picks up rows created by any user in the environment.
Why Organization scope?
In a real workplace, equipment requests come from many employees. Organization scope ensures the flow runs regardless of who submits the request. If you used User scope, the flow would only trigger for rows you personally create.
Add the approval action and condition branches
With the trigger configured, you need the flow to send an approval request and then branch based on the approver's decision.
- Below the trigger card, select the plus sign (+) and then select Add an action.
- Search for Approval and select the Start and wait for an approval action.
- In the Approval type dropdown, select Approve/Reject - First to respond.
- In the Title field, select the dynamic content icon (lightning bolt) and choose the Request Title column from the trigger outputs.
- In the Assigned to field, select the dynamic content icon and choose the Approver Email column.
- In the Details field, select the dynamic content icon and choose the Justification column.
What does this approval action do?
The Start and wait for an approval action sends an approval request to the email address in Assigned to. The flow pauses until the approver responds with Approve or Reject. The Approve/Reject - First to respond type means a single response completes the request immediately.
By mapping Title, Assigned to, and Details to dynamic content from the trigger, each approval email is personalized to the specific request.
Now add a Condition to branch the flow based on the approver's decision.
- Below the approval action, select the plus sign (+) and then select Add an action.
- Search for Condition and select Condition under Control.
- In the first Choose a value field, select the dynamic content icon and choose Outcome from the approval action outputs.
- Set the operator to is equal to.
- In the second Choose a value field, type Approve.
Approve is case-sensitive
The valid responses are Approve and Reject with exact capitalisation. Make sure you type Approve with a capital A.
Now configure the Yes branch (approved) and the No branch (rejected).
- In the If yes branch, select Add an action.
- Search for Update a row and select the Update a row action under Microsoft Dataverse.
- Set Table name to Equipment Requests.
- In the Row ID field, select the dynamic content icon and choose the unique identifier from the trigger (the Equipment Request row ID).
- Expand Show all or Advanced options to find the Status field.
- Set Status to Approved.
- In the If no branch, select Add an action.
- Add another Update a row action for the same Equipment Requests table.
- Set the Row ID to the same trigger row identifier.
- Set Status to Rejected.
- Select Save in the top-left corner of the flow designer.
What does the Condition do?
The Condition checks the Outcome value returned by the approval action. If the approver clicked Approve, the If yes branch runs and updates the Equipment Request row to Approved. If they clicked Reject, the If no branch runs and sets Status to Rejected.
Can't find the Status field in Update a row?
The Status column only appears after you select the correct table. Make sure Table name is set to your Equipment Request table first. Then expand Show all to reveal the Choice columns.
If you still cannot find it, help me find the Status field in the Dataverse Update a row action.
Test the approval flow end-to-end
The flow is saved and active. Now you will submit a request from the canvas app, receive the approval email, and verify the status updates in Dataverse.
- Switch back to your canvas app in Power Apps and open it in Preview mode (press the Play button in the top-right corner).
- Navigate to the Browse screen and select a category.
- On the Submit screen, fill in the form fields. In the Approver Email field, enter your own email address so you receive the approval.
- Submit the request.
- Open your email inbox. You should receive an approval email within a few minutes containing the request title and justification text.
- In the approval email, click Approve.
- Return to Power Automate and open My flows or the flow's run history to confirm the run completed successfully.
- Open the Equipment Request table in Dataverse. Verify the row you submitted now shows a Status of Approved.
What should I see?
The flow run history should show a successful run with green checkmarks on every action. The Equipment Request row in Dataverse should display Approved in the Status column. If you reject instead of approve, the status should show Rejected.
- Submit a second test request and this time click Reject in the approval email. Verify the row updates to Rejected in Dataverse.
Approval email not arriving?
Check that the Approver Email column on the submitted row contains a valid email address. The address must resolve to a user in your Microsoft 365 tenant.
Also check the flow run history for errors. If the run shows a failure on the approval action, the Assigned to field may have been empty or invalid.
If you are still stuck, help me troubleshoot why my Power Automate approval email is not arriving.
Your automated approval flow is live. Every new equipment request now triggers a real approval cycle that updates Dataverse automatically. Next up, you will build an instant flow that lets employees withdraw a pending request directly from the canvas app.
Create the Instant Flow for Withdrawals
Your automated flow handles the approval lifecycle, but what if an employee changes their mind before the approver responds? Right now there is no way to cancel a pending request from inside the app.
In this step, you will build an instant cloud flow that the canvas app calls directly when a user taps a Withdraw button. This introduces a second flow type: one that responds to a user action inside the app rather than reacting to a Dataverse event.
In this step, get ready to:
- Create an instant cloud flow with the Power Apps (V2) trigger and a text input parameter.
- Connect the flow to your canvas app and add a Withdraw button with conditional visibility.
- Test the full withdrawal cycle end to end.
Create the instant cloud flow
An instant flow runs only when explicitly triggered. The When Power Apps calls a flow (V2) trigger lets you define typed input parameters that the canvas app passes at runtime.
- Switch back to Power Automate (make.powerautomate.com) and open your project solution.
- Click + New at the top of the solution, then select Automation > Cloud flow > Instant.
- Enter a name for the flow, such as Withdraw Equipment Request.
- Under Choose how to trigger this flow, select When Power Apps calls a flow (V2).
- Click Create.
Why the V2 trigger?
The V2 trigger supports typed input parameters (text, number, file, boolean) that the canvas app fills in at call time. The older V1 trigger relied on untyped "Ask in Power Apps" tokens. The V2 pattern gives you explicit parameter names you can reference throughout the flow.
- In the trigger card, click + Add an input.
- Select Text as the input type.
- Enter RequestID as the parameter name.
What does RequestID do?
This parameter receives the unique identifier of the Equipment Request row the employee wants to withdraw. The canvas app will pass the selected row's ID at runtime so the flow knows which record to update.
- Below the trigger, click the + button to add a new action.
- Search for Update a row and select the Microsoft Dataverse connector's Update a row action.
- Set Table name to Equipment Requests.
- Set Row ID to the dynamic content value RequestID from the trigger.
- Expand Show all (or Advanced options) to reveal the Status column.
- Set the Status field to Withdrawn.
- Click Save in the command bar.
What does this flow do?
When the canvas app calls this flow, it passes the row's unique ID. The flow then finds that specific Equipment Request row in Dataverse and flips its Status choice to Withdrawn. The entire operation is a single action, keeping the flow fast and lightweight.
Don't see the Status column?
Make sure you selected the correct table (Equipment Requests, not Equipment Categories). Click Show all or Advanced options to reveal columns that are not shown by default.
Help me troubleshoot missing columns in the Update a row action.
Connect the flow to your canvas app
Now that the flow exists in your solution, you need to wire it into the canvas app so a button can call it.
- Switch back to Power Apps (make.powerapps.com) and open your canvas app for editing.
- In the app authoring menu on the left, select Power Automate.
- In the Power Automate pane, click Add a flow.
- Find and select your Withdraw Equipment Request flow from the list.
- The flow now appears under the In your app section of the pane.
What is the Power Automate pane?
The Power Automate pane inside Power Apps Studio lists every flow connected to your app. When you add a flow here, the app registers the flow's input schema so you can call it with .Run() directly from Power Fx formulas.
- Navigate to your My Requests screen.
- Select + Insert and add a Button control. Position it near the gallery.
- Set the button's Text property to "Withdraw".
- Set the button's Visible property to the following formula:
Gallery.Selected.Status = "Submitted"
Why conditional visibility?
The button only appears when the selected request has a Status of Submitted. Once a request is Approved, Rejected, or already Withdrawn, there is nothing to withdraw. Hiding the button prevents confusion and invalid operations.
- Select the Withdraw button and set its OnSelect property to the following formula:
WithdrawFlow.Run(Gallery.Selected.EquipmentRequestID);
Refresh('Equipment Request');
Notify("Request withdrawn", NotificationType.Success)
What does this formula do?
- WithdrawFlow.Run(Gallery.Selected.EquipmentRequestID) calls the instant flow and passes the unique row ID of the selected request.
- Refresh('Equipment Request') reloads the data source so the gallery reflects the updated status immediately.
- Notify("Request withdrawn", NotificationType.Success) shows a green confirmation banner at the top of the screen.
- Save the app by pressing Ctrl+S (Windows) or Cmd+S (macOS).
Flow name in your formula
The name you reference in the formula (WithdrawFlow in the example above) is the internal identifier Power Apps assigns when you add the flow. If your flow has spaces in its display name, Power Apps removes them. Check the Power Automate pane to confirm the exact reference name.
Getting a formula error on .Run()?
Make sure you added the flow via the Power Automate pane first. If the flow does not appear in the In your app section, Power Apps does not know about it and will show a name error.
Also confirm the flow uses the When Power Apps calls a flow (V2) trigger. Flows with other trigger types cannot be called from a canvas app.
Help me fix the .Run() formula error in my canvas app.
Test the withdrawal flow
Time to verify the full cycle: tap Withdraw in the app, confirm the status changes in Dataverse, and check that the button hides itself.
- Click the Play button (preview icon) in the top-right of Power Apps Studio to run the app in preview mode.
- Navigate to the My Requests screen.
- Select a request that has a Status of Submitted. Confirm the Withdraw button is visible.
- Tap the Withdraw button.
- You should see a green "Request withdrawn" notification banner at the top of the screen.
- The gallery refreshes and the status of that request now shows Withdrawn.
- Select that same request again. The Withdraw button should now be hidden because the status is no longer Submitted.
How do I double-check in Dataverse?
Open your Equipment Request table in the Dataverse data workspace. Find the row you just withdrew and confirm the Status column reads Withdrawn. This validates that the flow actually updated the record, not just the app's local display.
- Select any request with a status of Approved or Rejected. Verify the Withdraw button does not appear.
Button still showing for non-Submitted requests?
Double-check the Visible property of the button. It must reference the gallery's selected item status, not a hardcoded value. Ensure you are comparing against the exact choice label "Submitted" (case-sensitive).
Help me fix my Withdraw button's conditional visibility.
Your app now supports the full request lifecycle: submit, approve or reject, and withdraw. Next up, you will tackle the Secret Mission and add professional error handling with scopes plus a scheduled escalation flow.
Secret mission
Error Handling with Scopes and a Scheduled Escalation Flow
Your approval flow works, but what happens when something goes wrong mid-flow? And what about requests that sit pending for days with no response? In this secret mission, you'll add production-grade error handling using the try/catch scope pattern and build a scheduled flow that auto-escalates stale requests.
Clean Up Your Resources
Clean Up Your Resources
Decide whether to keep your resources running, pause them to come back later, or delete them entirely. This project runs entirely on a Power Platform developer environment, so there are no ongoing costs.
Resources you used:
- Two Dataverse tables (Equipment Category and Equipment Request).
- Three cloud flows (automated approval, instant withdrawal, scheduled escalation).
- One canvas app (Equipment Request app with three screens).
- One solution containing all of the above components.
Keep everything running
No action needed. Choose this if you plan to keep practising with the app or want to take portfolio screenshots for your PL-200 preparation.
- Your flows, app, and tables remain in the developer environment at no cost.
- The automated approval flow and scheduled escalation flow will continue to run when triggered.
Pause - I'll come back to this later
Turn off the cloud flows to prevent unnecessary runs while keeping everything intact for later.
- In Power Automate, select Solutions in the left navigation.
- Open your project solution.
- For each of your three flows (automated approval, instant withdrawal, scheduled escalation), select the vertical ellipsis (⋮) and choose Turn off.
- Your canvas app and Dataverse tables remain untouched. When you return, select the vertical ellipsis (⋮) on each flow and choose Turn on to resume.
Delete - I don't want to use this again
Remove all project components from your environment to start fresh. Because your solution is unmanaged, deleting the solution container alone does not remove the individual components. You need to delete each component from within the solution first.
- In Power Apps, select Solutions in the left navigation.
- Open your project solution.
- Select the canvas app, then select Delete from this environment on the command bar.
- Select each cloud flow (automated approval, instant withdrawal, scheduled escalation) one at a time and select Delete from this environment.
- Select the Equipment Request table, then select Delete from this environment. Repeat for the Equipment Category table.
- Navigate back to Solutions. Select (do not open) the now-empty solution and select Delete on the command bar.
Why delete tables last?
Dataverse tables have dependencies on the flows and app that reference them. Removing the app and flows first clears those dependencies so the tables can be deleted cleanly.
Nice Work!
Nice Work!
You just built a complete equipment request system from scratch. Employees can browse categories, submit requests, track statuses, and withdraw pending items, all backed by automated approval routing in Power Automate.
You've learned how to:
- Build a multi-screen canvas app connected to Dataverse with galleries, forms, navigation, variables, collections, and error handling using Power Fx.
- Create an automated cloud flow triggered by new Dataverse rows that routes approvals using the Start and wait for an approval action and updates statuses based on the outcome.
- Create an instant cloud flow using the Power Apps (V2) trigger, callable directly from a button in the canvas app to withdraw pending requests.
- Secret Mission: Applied the try/catch scope pattern with run-after configuration for robust error handling, and built a scheduled flow for time-based escalation logic.
Together with Project 1 (model-driven app, BPF, security roles, Dataverse modeling), this project covers the canvas app and cloud flow automation skills that make up roughly 50-55% of the PL-200 exam.
Ready to quiz yourself?