In my last post I broke down the progress bar in my multi-screen Events app. While I was in there, I noticed something else worth talking about — something that works perfectly well but that I would build very differently today. The app carries its data from screen to screen using around 25 global variables, one for almost every field on the form.
It runs fine. But it is a lot of plumbing, and every one of those variables is a little thing that can drift, get misnamed, or quietly hold the wrong value. In this post I will show you the pattern I used, explain why I would move away from it, and walk you through two cleaner approaches you can rebuild yourself.
What the app does today
The form spans several screens — event details, logistics, food, materials, and so on — and finishes on an overview screen where everything is submitted at once. To get the data from the early screens all the way to that final submit, each Next button copies every field into its own global variable:
powerfx
// On the "Next" button of the Event Details screen:
Set(Var_Title, DataCardValue45.Text);
Set(Var_StartDate, DataCardValue46.SelectedDate);
Set(Var_SectorCommunity, DataCardValue43.SelectedItems);
Navigate(LogisticScreen, ScreenTransition.Fade)
Then, on the overview screen, each card reads its value back out of the matching variable:
powerfx
// Default property of the Title card on the overview form:
Var_Title
Do that for every field on every screen and you end up with a long list of Var_Title, Var_StartDate, Var_Location, Var_Lunch, Var_Wifi… roughly 25 of them.
Why I would change it
Nothing here is broken. But three things bug me:
Every field is wired up twice. Once to capture it into a variable, once to read it back on the overview. Add a new field and you now edit it in three places: the input card, the Set on the Next button, and the Default on the overview. Miss one and you get a value that silently doesn’t save.
The variable list becomes a wall. Open the Variables panel and you are looking at 25 near-identical names. When something is wrong, “which variable holds the room setup again?” is a question you should never have to ask.
Globals are global. A variable set with Set is visible and editable from every screen in the app. With 25 of them floating around, it is easy to accidentally overwrite one from the wrong place, and hard to reason about what holds what at any given moment.
So let’s collapse all of that down.
Approach 1: one record instead of 25 variables
Here is the key idea: instead of 25 separate variables, keep one variable that is a record — a little bundle of named fields. Power Apps records use curly braces:
powerfx
{ Title: "Kick-off", StartDate: Date(2026, 9, 1) }
The catch is that each screen only knows about its own fields, so we can’t build the whole record in one go. Instead, each Next button merges its fields into the record as the user moves along. The tool for merging one record into another is Patch:
powerfx
// On the "Next" button of the Event Details screen:
Set(
gblEvent,
Patch(
gblEvent,
{
Title: DataCardValue45.Text,
StartDate: DataCardValue46.SelectedDate,
SectorCommunity: DataCardValue43.SelectedItems
}
)
);
Navigate(LogisticScreen, ScreenTransition.Fade)
Patch(gblEvent, {…}) takes the existing gblEvent record and returns a new copy with these fields added or updated. Each screen tops up the same record with its own slice of data.
Before any of this runs, give the record a starting shape. Do it once in the app’s OnStart, or on the first screen’s OnVisible when someone begins a new request:
powerfx
Set(
gblEvent,
{
Title: "",
StartDate: Blank(),
SectorCommunity: Blank(),
Location: Blank()
// ...one line per field
}
)
Now, on the overview screen, instead of 25 different variable names, everything reads out of the one record:
powerfx
// Default of the Title card:
gblEvent.Title
// Default of the Start Date card:
gblEvent.StartDate
That is the whole change. One variable, one clear structure, and the field names actually describe what they hold. Adding a new field now means editing the input card and one line in the Patch — the overview reads gblEvent.NewField and you’re done.
Approach 2: skip the variables and Patch the list directly
Approach 1 already fixes the “wall of variables” problem. But there is an even cleaner endgame worth knowing about, especially once you’re comfortable.
Right now the app has a form control on almost every screen, all pointed at the same SharePoint list, and the submit button resets each of those forms before submitting one of them. (Power Apps’ own App Checker flags this as a “cross-screen dependency,” because it reaches across screens that may not even be loaded yet.)
If you’re already collecting everything into gblEvent, you don’t need all those forms. You can write the record straight to SharePoint with a single Patch on the submit button:
powerfx
// On the Submit button:
Patch(
Events, // your SharePoint list
Defaults(Events), // Defaults(...) means "create a new item"
{
Title: gblEvent.Title,
'Start Date': gblEvent.StartDate,
Location: gblEvent.Location,
Lunch: gblEvent.Lunch
// ...map each list column to its record field
}
);
If(
IsEmpty(Errors(Events)),
Notify("Your event request was submitted successfully!", NotificationType.Success);
Navigate(ConfirmationScreen, ScreenTransition.Fade),
Notify("Something went wrong: " & First(Errors(Events)).Message, NotificationType.Error)
)
Patch with Defaults(Events) creates one brand-new list item and fills it with your collected values. No forms scattered across screens, no resetting forms on other screens, and one clear place where the record is saved. Notice I also pulled the actual error text into the notification with First(Errors(Events)).Message — much more helpful than a generic “something went wrong.”
A small note on SharePoint: choice and person columns don’t take a plain text value — they expect a specific record shape. So when you map those in the Patch, you may need the {Value: …} form for choices. Test one tricky column early rather than all of them at the end.
Which one should you use?
If you’re newer to Power Apps, start with Approach 1. It’s the smaller change — you keep your existing forms and just swap 25 variables for one record. You get most of the readability benefit immediately, and it’s easy to reason about.
When you’re ready to simplify the architecture properly, Approach 2 is where you want to land. It removes the per-screen forms, kills the cross-screen dependency warning, and gives you one obvious spot where data gets written.
Wrapping up
None of this makes the app work better for the user today — the current version submits their event request just fine. What it buys you is a form that’s easier to read, safer to change, and quicker to debug six months from now when you’ve forgotten every DataCardValue number. Collapse those 25 globals into one gblEvent record, and eventually let a single Patch do the saving.
Fewer moving parts, fewer places for a value to go missing. Your future self, adding “field number 26,” will be grateful. Happy building!