Where you're starting from
colSystems; validation blocks bad submissions with red borders and per-row messages. A fully valid Submit click already sets gblShowConfirm — it just has nothing to show yet. That's the first thing we fix.<YOUR-SITE-URL> or <IAM-DL-EMAIL>, substitute your own SharePoint site URL and the IAM distribution list address.btnConfirmYes is a value you enter — tap the chip to copy it (the ⧉ mark is the reminder), then paste it where the step says. A key cap like Ctrl+A is pressed on the keyboard. Dark boxes are complete formulas with their own Copy button. Paste, never retype.Phase 1 — The confirmation popup
C1Build the confirmation popup
Six controls, inserted in this order so they stack correctly (later inserts sit on top). All six get the same Visible formula, so the whole popup appears and disappears as one. To rename a control: double-click its name in the Tree view → paste → Enter.
scrMain at the top of the Tree view) before inserting — if a gallery control is selected, the new control lands inside the gallery and replicates into every row. Check after each insert: in the Tree view the new control sits at screen level, not indented under galSystems. If it's nested: delete it, click the screen, insert again.- + Insert (left rail) → search
Rectangle→ click it → rename itrecOverlay. This is the full-screen dimmer. - + Insert → search
Rectangle→ rename itrecConfirmCard. This is the white card. - + Insert → search
Text label→ rename itlblConfirmTitle. - + Insert → search
Text label→ rename itlblConfirmMsg. - + Insert → search
Button→ rename itbtnConfirmYes→ property dropdown (top-left, next to the fx bar) → Text → Ctrl+A → paste (quotes included):"Submit". - + Insert → search
Button→ rename itbtnConfirmNo→ property dropdown → Text → Ctrl+A → paste:"Cancel".
Size and place them: select each control, then type these into the Properties pane (right side) → Position → X / Y and Size → Width / Height. Every number is tap-to-copy:
- recOverlay
- X
0· Y0· Width1366· Height768 - recConfirmCard
- X
433· Y234· Width500· Height300 - lblConfirmTitle
- X
457· Y254· Width452· Height40 - lblConfirmMsg
- X
457· Y300· Width452· Height130 - btnConfirmYes
- X
693· Y460· Width216· Height48 - btnConfirmNo
- X
457· Y460· Width216· Height48
Fills and fonts cannot be pasted into the Properties pane's colour picker — they go through the formula bar. Select recOverlay → property dropdown → Fill → Ctrl+A → paste:
recOverlay · Fill
RGBA(0, 0, 0, 0.4)Select recConfirmCard → property dropdown → Fill → Ctrl+A → paste:
recConfirmCard · Fill
RGBA(255, 255, 255, 1)Select lblConfirmTitle → right pane → Font weight Bold · Font size 22.
Now the formulas. Select each of the six controls in turn → property dropdown → Visible → Ctrl+A → paste (a new control's Visible already contains true — Ctrl+A replaces it):
all six popup controls · Visible
gblShowConfirmSelect lblConfirmTitle → property dropdown → Text → Ctrl+A → paste:
lblConfirmTitle · Text
"Confirm submission"Select lblConfirmMsg → property dropdown → Text → Ctrl+A → paste:
lblConfirmMsg · Text
"You are about to submit " & CountRows(colSystems) & " system record(s) to the 3rd party inventory. The IAM team will be notified by email. Do you want to proceed?"Select btnConfirmNo → property dropdown → OnSelect → Ctrl+A → paste (a new button's OnSelect already contains false):
btnConfirmNo · OnSelect
Set(gblShowConfirm, false)Phase 2 — The notification flow
C2Create the flow and its four inputs
The flow is built in Power Automate, in the same environment as your app.
- Open
https://make.powerautomate.com→ check the environment picker (top right) matches the app's environment. - Create (left rail) → Instant cloud flow.
- Flow name: paste
SystemDeclarationNotify. Choose the trigger PowerApps (V2) → Create. - Click the PowerApps (V2) trigger card → Add an input → Text. The name goes in the box labeled Input on the new row — Ctrl+A → paste
ResponderName. - Add an input → Text →
ResponderEmail. - Add an input → Text →
SubmissionDate. - Add an input → Text →
SystemCount.
ResponderName, ResponderEmail, SubmissionDate, SystemCount. When the app calls SystemDeclarationNotify.Run(...) in C5, the arguments are matched by position. All four are Text on purpose: the app pre-formats the date and count, which sidesteps timezone and locale conversion entirely.C3The email to the IAM team
- Under the trigger: New step (in the new designer: + Add an action) → search
Send an email (V2)→ pick the Office 365 Outlook action. - To: your IAM distribution list —
<IAM-DL-EMAIL>. - Subject: paste exactly:
Send an email (V2) · Subject
New Third-Party Application Submission ReceivedBody: click the </> (code view) toggle in the body field's top-right, then paste this skeleton:
Send an email (V2) · Body (HTML)
<p>A new third-party application declaration has been submitted.</p>
<ul>
<li><b>Responder:</b> </li>
<li><b>Submission date:</b> </li>
<li><b>Number of declared systems:</b> </li>
</ul>
<p><a href="<YOUR-SITE-URL>/Lists/3rd%20party%20inventory/AllItems.aspx">Open the 3rd party inventory list</a></p>- Place the cursor after Responder: (before the closing
</li>), then click the lightning-bolt Dynamic content button (or the Add dynamic content link under the field) → insert theResponderNamechip. - Same for Submission date: → insert
SubmissionDate. - Same for Number of declared systems: → insert
SystemCount. - Fix the link: replace
<YOUR-SITE-URL>with your real site URL. - Save the flow.
ResponderEmail dynamic content chip. The submitter gets a copy of what IAM received — a nice audit courtesy, and it's why the app passes the email at all.SystemDeclarationNotify. Renaming the flow after C4 breaks SystemDeclarationNotify.Run(...) in the app — the fix is to remove and re-add the flow in the Power Automate pane. Name it right once, now, before it ever touches the app.C4Connect the flow to the app
- Back in Power Apps Studio (your app open for editing).
- Left rail → Power Automate (the flow icon) → Add flow.
- Pick
SystemDeclarationNotifyfrom the list.
SystemDeclarationNotify.Run( — IntelliSense autocompletes the flow name and hints four text arguments. Press Esc without saving the test-typing.Phase 3 — Wire the submit
C5The submit formula — write, notify, succeed
One paste. It writes every row of colSystems to the list, stamps the audit trail (responder name, email, date/time), calls the flow, and flips to the success screen. It reads only the collection — never control state — which is the whole point of the Part 1 architecture.
Tree view → click btnConfirmYes → property dropdown → OnSelect → Ctrl+A → paste (the button's OnSelect already contains false — Ctrl+A replaces it; pasting without it breaks the formula):
btnConfirmYes · OnSelect
Set(gblSubmitting, true);
IfError(
ForAll(colSystems As row,
Patch('3rd party inventory', Defaults('3rd party inventory'),
{
'Application Name': row.AppName,
'Vendor/ Provider Name': row.Vendor,
'Business owner': row.BizOwner,
'Application Purpose': row.Purpose,
'IT Custodian': row.Custodian,
'Admin Accounts Used': row.AdminAccts,
'Permissions / Access levels': row.Permissions,
'Support / Vendor Contact Information': row.SupportContact,
'IAM Role': row.IAMRole,
'Access Link': row.AccessLink,
'Division ': row.Division,
Status: row.Status,
'Handover Status': row.Handover,
'Number of Accounts': row.NumAccts,
'Submission Date': Now(),
'Responder Name': User().FullName,
'Responder Email': User().Email
}
)
),
Set(gblSubmitting, false);
Notify("Submission failed — please try again. " & FirstError.Message, NotificationType.Error),
SystemDeclarationNotify.Run(User().FullName, User().Email, Text(Now(), "dd mmm yyyy hh:mm"), Text(CountRows(colSystems)));
Set(gblShowConfirm, false);
Set(gblShowErrors, false);
Set(gblSubmitting, false);
Set(gblShowSuccess, true)
)'Vendor/ Provider Name' (space after the slash), 'Business owner' (lowercase o), 'Permissions / Access levels' (lowercase l), and 'Division ' — with a trailing space. The paste above already has them exactly right. If you ever retype one, accept IntelliSense's autocomplete — a hand-typed 'Division' (no space) will not resolve.IAM Role, Division , Status, Handover Status and Number of Accounts as text, Submission Date as Date and Time — the live list data backs these. If you noted a different type at A1 (or the formula bar flags a line), apply the matching one-line fix:· Column is Choice → wrap in a record:
'IAM Role': {Value: row.IAMRole} — same treatment for 'Division ', Status, 'Handover Status'.·
Number of Accounts is a Number column → 'Number of Accounts': Value(row.NumAccts).·
Submission Date is Text → 'Submission Date': Text(Now(), "yyyy-mm-dd hh:mm").Guessed wrong? The formula bar flags that exact line with "expected record value, found text" (or the reverse). Fix just that line per the rules above.
error). If IfError shows as an unknown function, flip that switch on and re-paste.btnConfirmYes. Don't test-click yet — the success screen it flips to doesn't exist until C6.C6The success screen and the reset
Same recipe as C1 — five controls, inserted in order, all sharing one Visible flag. Rename each by double-clicking its name in the Tree view → paste → Enter. Geometry goes in the Properties pane → Position / Size, exactly as in C1:
scrMain in the Tree view; then confirm the new control sits at screen level, not indented under galSystems. If it's nested: delete it, click the screen, insert again.- + Insert → search
Rectangle→ renamerecSuccessOverlay— X0· Y0· Width1366· Height768. - + Insert → search
Rectangle→ renamerecSuccessCard— X433· Y234· Width500· Height300. - + Insert → search
Text label→ renamelblSuccessTitle— X457· Y254· Width452· Height40· right pane → Font weight Bold · Font size22. - + Insert → search
Text label→ renamelblSuccessMsg— X457· Y300· Width452· Height130. - + Insert → search
Button→ renamebtnNewDeclaration— X457· Y460· Width452· Height48→ property dropdown → Text → Ctrl+A → paste:"Start a new declaration".
The two fills go through the formula bar (not the Properties pane). Select recSuccessOverlay → property dropdown → Fill → Ctrl+A → paste:
recSuccessOverlay · Fill
RGBA(0, 0, 0, 0.4)Select recSuccessCard → property dropdown → Fill → Ctrl+A → paste:
recSuccessCard · Fill
RGBA(255, 255, 255, 1)Select each of the five controls → property dropdown → Visible → Ctrl+A → paste:
all five success controls · Visible
gblShowSuccessSelect lblSuccessTitle → property dropdown → Text → Ctrl+A → paste:
lblSuccessTitle · Text
"Declaration submitted 🎉"Select lblSuccessMsg → property dropdown → Text → Ctrl+A → paste:
lblSuccessMsg · Text
"Your system records have been added to the 3rd party inventory and the IAM team has been notified. You can close the app or start a new declaration."Select btnNewDeclaration → property dropdown → OnSelect → Ctrl+A → paste:
btnNewDeclaration · OnSelect
Set(gblNextSeq, 2);
ClearCollect(colSystems, {RowID: GUID(), SeqNo: 1, AppName: "", Vendor: "", BizOwner: "", Purpose: "", Custodian: "", AdminAccts: "", Permissions: "", SupportContact: "", IAMRole: "", AccessLink: "", Division: "", Status: "", Handover: "", NumAccts: ""});
Set(gblShowSuccess, false)colSystems with a brand-new RowID forces the gallery to build brand-new items, so no leftover control state from the previous declaration can bleed into the next one. No Reset() calls needed — the collection is, as always, the single source of truth.recSuccessOverlay → property dropdown → Visible → Ctrl+A → temporarily type true — repeat for the card, title, message and button (or Ctrl-click all five in the Tree view and set them once). The card reads cleanly and the button spans under the message. Then restore each Visible to gblShowSuccess.Phase 4 — Prove it, then ship it
C7Check the audit trail with one real record
- Preview the app (F5). Fill the single row with obviously-test values (e.g. Application Name
ZZ Test App — delete me), pick any dropdown values, a valid URL and a number. - Submit → the popup appears → Submit.
- The success screen appears. Press Esc to leave Preview, then open the
3rd party inventorylist in the browser.
Responder Name is your full name, Responder Email is your address, Submission Date is just now. SharePoint's built-in Created By / Created corroborate them. The IAM mailbox (or your CC copy) received the notification. Delete the test item when you're done looking.C8The end-to-end test script
The full journey, exactly as a business user will drive it. F5 from the top:
- + Add System twice → three rows. Fill all three completely (distinct app names — Test A, Test B, Test C).
- Submit → popup says "3 system record(s)" → press Cancel → popup closes, all three rows intact.
- Submit again → Submit on the popup → success screen appears.
- In SharePoint: three new items, values in the right columns — spot-check that each row's division landed in the
Divisioncolumn (the trailing-space one) and the number inNumber of Accounts. - The IAM email arrived: subject exact, responder name right, Number of declared systems: 3, and the link opens the list.
- Back in the app: Start a new declaration → one blank row, count label says 1, no red anywhere.
- Clean up the three test items in SharePoint.
C9The victory lap — publish and share
- File → Save → Publish → Publish this version.
- Back on the app's detail page (or File → Share): Share the app with your users or a security group.
- Give the same people Contribute permission on the
3rd party inventorylist — the app writes as the signed-in user, so without list rights their submits fail. The clicks: open the list → gear icon → List settings → Permissions for this list → Grant Permissions → enter the users or group → choose Contribute — or ask your site owner to do it. - Flow check: in Power Automate, open
SystemDeclarationNotify→ Details → confirm its connections are healthy and, under Run only users, that app users are allowed to run it (adding the flow to the app normally handles this — verify once).
colSystems. Every one of those reads a local collection, not SharePoint — delegation doesn't apply, nothing is truncated, nothing blocks publishing.