Somewhere in your company right now, someone just emailed a PDF to request office supplies. Their manager printed it, signed it with a pen, scanned it back, and emailed it to finance. Finance screenshotted the email chain, saved it in a folder called "Approvals 2026 FINAL v3", and will manually enter the data into a spreadsheet by Friday.
Every single step of that is fixable. With Power Apps Canvas, you can build a purchase request system that handles the form, the approval routing, the status tracking, and the audit trail — without writing a line of backend code. Finance sees a structured inbox. Managers approve from their phone. Requesters get real-time status. Every decision is logged automatically.
This guide walks you through the exact architecture and screens we build for clients. It covers the SharePoint data model, all three screens of the canvas app, the Power Automate connection, and the formulas that make it work.
What You're Building
The finished system has three components working together:
- A Power Apps Canvas App with four screens: New Request form, My Requests tracker, Approval Inbox (manager view), and an Admin Dashboard.
- Two SharePoint lists as the data backend: one for purchase requests, one for categories/vendors.
- A Power Automate flow that sends approval notifications, updates statuses, and timestamps every action.
Power Platform makers, SharePoint admins, and IT teams who want to understand how a production-grade canvas app is architected — not just the basics. We'll go beyond the drag-and-drop tutorial and into real formulas, delegation issues, and design patterns that hold up at scale.
Step 1 — The SharePoint Data Model
Canvas apps can use Dataverse, SharePoint, SQL, or any connector as a data source. For most Microsoft 365 organisations without a premium Power Platform licence, SharePoint is the right choice. It's included, it's familiar to admins, and it supports the permissions model you need.
Create two lists in your SharePoint site:
List 1: PurchaseRequests
This is the core table. Every field you expose in the form should have a corresponding column here:
- Title (single line) — Item description
- RequestCategory (choice) — IT Equipment, Office Supplies, Software, Services, Other
- Vendor (single line) — Supplier name
- Quantity (number)
- UnitPrice (currency)
- TotalAmount (calculated:
=[Quantity]*[UnitPrice]) - BusinessJustification (multi-line text)
- RequiredByDate (date)
- Status (choice) — Pending, Under Review, Approved, Rejected, Cancelled
- ApproverComments (multi-line text)
- RequestedBy (person) — auto-populated from current user
- ApprovedBy (person) — populated by the flow
- ApprovedDate (date/time) — populated by the flow
- Priority (choice) — Low, Normal, High, Urgent
List 2: PurchaseCategories
A lookup list for category-specific approval routing (some categories may need a different approver chain):
- Title — Category name
- DefaultApprover (person) — who approves this category by default
- BudgetThreshold (currency) — above this, escalate to senior approver
- SeniorApprover (person) — for high-value requests in this category
Power Apps with SharePoint hits a delegation limit of 500 rows by default (max 2000 with the setting changed). If your PurchaseRequests list will exceed this, filter by date on screen load — e.g. show requests from the last 90 days — rather than loading the full list. This is the most common production issue with SharePoint-backed canvas apps.
Step 2 — The Four App Screens
Power Apps Canvas is a screen-based model. Think of each screen as a separate page in a web app. Navigation between them uses the Navigate() function. Here's what each screen does and why.
New Request Form
An EditForm control bound to PurchaseRequests. Requesters fill in item details, category, vendor, and justification. A submit button triggers the Power Automate flow on save.
My Requests
A Gallery showing requests where RequestedBy.Email = User().Email. Colour-coded status badges. Tap a row to see full details including approver comments.
Approval Inbox
Manager-only screen. Gallery filtered to pending requests where the user is the assigned approver. Approve/Reject buttons trigger a separate Power Automate flow and update status inline.
Admin Dashboard
Finance/admin view. Shows aggregate stats (total pending, total approved value this month, average approval time). Searchable full request list with export to CSV.
Role-based screen routing on app launch
The app's OnStart property should detect the user's role and navigate to the right screen automatically. Set this on App.OnStart:
// Detect role on load — add users to these SharePoint groups Set(varIsAdmin, !IsBlank(LookUp( PurchaseCategories, DefaultApprover.Email = User().Email ))); Set(varCurrentUser, User()); // Navigate to role-appropriate home screen If(varIsAdmin, Navigate(ApprovalInbox, ScreenTransition.Fade), Navigate(MyRequests, ScreenTransition.Fade) );
Step 3 — Building the New Request Screen
Insert an Edit Form control (not a Display Form). Set its DataSource to PurchaseRequests and its DefaultMode to FormMode.New. Power Apps will auto-generate all the fields from your SharePoint columns — then you remove the ones users shouldn't fill in themselves (Status, ApprovedBy, etc.).
Key properties to configure on the form:
- Set RequestedBy DefaultValue to
User()and mark it read-only - Set Status DefaultValue to
"Pending"— hidden from the user - Add a conditional label showing total cost:
Text(Value(txtQuantity.Text) * Value(txtUnitPrice.Text), "[$-en-GB]£#,##0.00") - Validate required fields before enabling the Submit button
Submit button logic
// Validate before submit If( IsBlank(DataCardValue_Title.Text) || IsBlank(DataCardValue_Vendor.Text) || IsBlank(DataCardValue_Justification.Text), // Show validation error Notify("Please complete all required fields.", NotificationType.Error), // Submit the form — OnSuccess triggers the flow SubmitForm(NewRequestForm); Notify("Request submitted — your manager will be notified.", NotificationType.Success); Navigate(MyRequests, ScreenTransition.Fade) );
Step 4 — The Approval Inbox (Manager Screen)
This is the screen managers open when they get a notification email. It shows all requests pending their approval, ordered by priority then date.
The Gallery's Items property:
SortByColumns( Filter( PurchaseRequests, Status = "Pending", // Dynamic approver lookup based on category LookUp( PurchaseCategories, Title = ThisRecord.RequestCategory, If(ThisRecord.TotalAmount > BudgetThreshold, SeniorApprover.Email, DefaultApprover.Email ) ) = User().Email ), "Priority", Descending, "Created", Ascending )
Each gallery row has an Approve and Reject button. These buttons update the SharePoint item directly AND trigger a flow to notify the requester:
Patch( PurchaseRequests, ThisItem, { Status: "Approved", ApprovedBy: User(), ApprovedDate: Now(), ApproverComments: txtApproverComments.Text } ); // Trigger notification flow ApprovalNotificationFlow.Run( ThisItem.RequestedBy.Email, ThisItem.Title, "Approved", txtApproverComments.Text ); Notify("Request approved and requester notified.", NotificationType.Success); Refresh(PurchaseRequests);
Step 5 — Connect Power Automate
You need two flows. Build them in Power Automate, then add them to the canvas app via Action → Power Automate.
Flow 1: New Request Notification
Triggered from the app when a new request is submitted. It looks up the correct approver from PurchaseCategories based on the request total and sends them an approval email with Approve/Reject action links built in.
- Trigger: PowerApps (V2) — accepts request ID, category, amount, requester name
- Action: Get item from PurchaseCategories to find approver email
- Condition: If amount > BudgetThreshold → use SeniorApprover, else use DefaultApprover
- Action: Send an email (V2) with formatted HTML body
- Optional: Post an adaptive card to the approver's Teams channel
Flow 2: Status Update Notification
Triggered from the app when a manager approves or rejects. Sends the requester a confirmation email with the decision and any comments. Updates the SharePoint item timestamp (Power Apps Patch doesn't update Modified automatically in all scenarios).
For a better manager experience, send the approval as an Adaptive Card in Teams rather than an email. The manager can approve directly inside Teams without opening the app. Use the "Post an Adaptive Card and wait for a response" action in Power Automate. This is the pattern that gets approval rates above 90% in our client deployments — the less friction, the faster the decision.
Key Formulas Reference
These are the formulas that appear in almost every production canvas app. Save this section.
// Filter a gallery by current user Filter(PurchaseRequests, RequestedBy.Email = User().Email) // Format currency dynamically Text(ThisItem.TotalAmount, "[$-en-GB]£#,##0.00") // Colour-code status badges Switch(ThisItem.Status, "Approved", RGBA(22,163,74,1), "Rejected", RGBA(220,38,38,1), "Pending", RGBA(217,119,6,1), RGBA(100,116,139,1) ) // Conditional visibility — show admin section only varIsAdmin // Date difference for "days waiting" DateDiff(ThisItem.Created, Now(), Days) // Safe number formatting (prevents blank/null errors) If(IsBlank(txtQuantity.Text), 0, Value(txtQuantity.Text))
When to Use Power Apps vs Power Automate vs SPFx
This is the question every enterprise Microsoft 365 team faces. They're not competing tools — each is optimised for a different job. Here's the honest breakdown:
| Scenario | Power Apps Canvas | Power Automate | SPFx Web Part |
|---|---|---|---|
| Custom data entry form for staff | ✓ Best choice | Not for UX | Possible |
| Automated approval routing | Trigger only | ✓ Best choice | Backend needed |
| SharePoint intranet page component | Via iframe | Not applicable | ✓ Best choice |
| Mobile-first employee app | ✓ Best choice | Not for UX | Responsive only |
| Complex data calculations / reporting | Limited delegation | Not for display | ✓ Full control |
| IT Request / Help Desk ticket | ✓ Best choice | Routing only | Possible |
| Real-time Teams notification | Not applicable | ✓ Best choice | Via Graph API |
The short rule: Power Apps Canvas for the form experience, Power Automate for the logic that runs in the background, SPFx when you need something embedded directly in SharePoint's UI. In a purchase approval system, you need all three working together.
Production Gotchas to Know Before You Deploy
- Delegation limit — As mentioned, SharePoint caps at 2000 delegable rows. Filter by Status and date range on gallery load rather than pulling everything. Use
Filter(PurchaseRequests, Status="Pending", Created >= DateAdd(Now(), -90, Days))as your base query. - Offline behaviour — Canvas apps don't work offline by default. If your users are on-site without reliable internet, consider a model-driven app with offline sync or a Flutter mobile app instead.
- Named formula caching — Avoid calling
User()repeatedly inside galleries. Set it once in App.OnStart into a variable (Set(varCurrentUser, User())) and reference that. It's noticeably faster on load. - Version management — Power Apps saves versions automatically. Publish only when you're ready — unpublished changes are visible to you but not to users. Tell your team this, or someone will close a browser tab mid-build and wonder where their changes went.
- Responsive layout — If users will access this on both desktop and mobile, enable the responsive layout setting in the app settings. Otherwise set fixed canvas dimensions for desktop and build a separate phone app.
Key Takeaways
Power Apps Canvas is the right tool for staff-facing forms and request systems — it produces a full mobile+desktop app experience without writing backend code.
Model your SharePoint lists carefully before building the app. Changing column types after the app is built breaks data card bindings — schema first, canvas second.
Role-based screen routing in App.OnStart gives different users a different home screen without needing separate apps — one app, all roles.
Teams Adaptive Cards for approvals dramatically improve approval response rates compared to email-only notifications — managers can act without leaving Teams.
Plan for delegation limits early. Filter SharePoint data by date and status on load. A gallery trying to display 5,000 rows will be slow and unreliable — clamp it to the relevant window.