6.3 Variables (Context, Global), Collections & State Management
Key Takeaways
- Context variables created via UpdateContext({locVar: value}) are strictly scoped to the screen where they are declared and can be passed across screens via the Navigate() function.
- Global variables created via Set(gblVar, value) are app-scoped and accessible across all screens, ideal for user profiles, theme tokens, and global application state.
- Collections created via ClearCollect(), Collect(), and manipulated via Patch(), Remove(), and UpdateIf() provide in-memory tabular structures for caching, shopping carts, and multi-record staging.
- Canvas app state should follow declarative principles: makers should bind directly to control properties and data sources where possible, reserving variables for true stateful transitions.
- Offline capability can be implemented using SaveData() and LoadData() to serialize in-memory collections to encrypted local device storage, synchronized back via Connection.Connected event triggers.
Variables (Context, Global), Collections & State Management
State management is the backbone of dynamic, interactive canvas applications. While Power Apps encourages a declarative, formula-first paradigm, enterprise applications frequently require maintaining transient user state—such as tracking multi-step wizard progress, managing offline shopping carts, buffering uncommitted records, and storing user authorization profiles. For the PL-200: Microsoft Power Platform Functional Consultant exam, you must master the differences, scope, lifecycles, and performance implications of Context Variables, Global Variables, Collections, and local storage caching via SaveData and LoadData.
1. The Three Tiers of Canvas App State
Power Apps provides three distinct state containers, each scoped to a specific architectural layer.
+-----------------------------------------------------------------------------+
| CANVAS APP STATE MANAGEMENT TIERS |
| |
| +---------------------------------------------------------------------+ |
| | 1. CONTEXT VARIABLES (Screen Scoped) | |
| | - Created via: UpdateContext({ locFilter: "Active", locStep: 2 })| |
| | - Accessible ONLY on the screen where declared | |
| | - Passed between screens via: Navigate(Target, None, { ... }) | |
| +---------------------------------------------------------------------+ |
| |
| +---------------------------------------------------------------------+ |
| | 2. GLOBAL VARIABLES (App Scoped) | |
| | - Created via: Set(gblCurrentUser, User()) | |
| | - Accessible across ALL screens in the entire application | |
| | - Stores scalar values, records, or objects | |
| +---------------------------------------------------------------------+ |
| |
| +---------------------------------------------------------------------+ |
| | 3. COLLECTIONS (In-Memory Tabular Store) | |
| | - Created via: ClearCollect(colCart, Table), Collect(colCart, {})| |
| | - Full 2-dimensional table stored in client device RAM | |
| | - Manipulated via: Patch, Remove, RemoveIf, UpdateIf | |
| +---------------------------------------------------------------------+ |
+-----------------------------------------------------------------------------+
Comparative Architectural Matrix
| Dimension | Context Variables | Global Variables | Collections |
|---|---|---|---|
| Creation Function | UpdateContext({ locVar: value }) | Set(gblVar, value) | ClearCollect(col, ...), Collect(col, ...) |
| Scope | Single Screen | Entire App (All screens) | Entire App (All screens) |
| Data Structure | Scalar, Record, or Table | Scalar, Record, or Table | Tabular Data (Rows & Columns) |
| Memory Location | Screen Context Memory | Application Session RAM | Application Session RAM |
| Navigation Passing | Supported via Navigate() third parameter | Not required (globally visible) | Not required (globally visible) |
| Offline Serialization | Not directly serializable | Not directly serializable | Supported via SaveData() / LoadData() |
| Standard Naming | Prefix loc (e.g., locIsSubmitting) | Prefix gbl (e.g., gblUserRole) | Prefix col (e.g., colPendingOrders) |
2. Context Variables (UpdateContext)
Context variables hold state specific to a single screen. They cannot be directly read or modified by controls on another screen.
Syntax and Behavioral Mechanics
Context variables are declared using a record syntax containing key-value pairs wrapped in curly braces ({}):
// Updating multiple context variables in a single formula
UpdateContext({
locShowConfirmDialog: true,
locSelectedTab: "Equipment",
locValidationErrors: 0
})
Passing Context Across Screens via Navigate()
You can initialize or update context variables on a target screen during navigation by utilizing the optional third parameter of Navigate():
Navigate(
WorkOrderEditScreen,
ScreenTransition.None,
{
locCurrentWorkOrderId: Gallery_WorkOrders.Selected.WorkOrderId,
locFormMode: FormMode.Edit,
locSourceScreen: "Dashboard"
}
)
When WorkOrderEditScreen opens, locCurrentWorkOrderId is immediately available in memory before OnVisible executes.
Resetting Context Variables
To clear or reset a context variable, update its value to Blank() or its default primitive:
UpdateContext({ locShowConfirmDialog: false, locSelectedRecord: Blank() })
3. Global Variables (Set)
Global variables hold state across the entire application lifecycle. Once defined, any control or formula across any screen can read and modify the variable.
Syntax and Usage
Global variables are created and updated using the Set(VariableName, Value) function:
// Storing a scalar string
Set(gblEnvironmentName, "Production");
// Storing a complete Dataverse record
Set(gblCurrentAccount, LookUp(Accounts, AccountId = GUID("a1b2c3d4-...")));
// Storing an object or complex record
Set(gblUserSession, {
FullName: User().FullName,
Email: User().Email,
Role: LookUp(UserSecurityRoles, UserEmail = User().Email).RoleName,
LoggedInAt: Now()
});
[!NOTE] Declarative Best Practice: Do not overuse global variables. If a value can be derived directly via a formula (e.g.,
Label1.Text = Gallery1.Selected.AccountName), bind directly toGallery1.Selected.AccountNamerather than creating a global variable onGallery1.OnSelect. Unnecessary variables increase memory overhead and make debugging difficult.
4. Collections: In-Memory Tabular Data
Collections are temporary, in-memory database tables that exist in client RAM during the user's active session. They provide full two-dimensional tabular capabilities, allowing you to add, edit, filter, sort, and remove rows locally without making immediate backend network calls.
+-----------------------------------------------------------------------------+
| COLLECTION MANIPULATION PIPELINE |
| |
| 1. POPULATE / RESET: |
| ClearCollect(colOrderItems, Filter(Products, Category = "Hardware")) |
| |
| 2. APPEND NEW ITEM: |
| Collect(colOrderItems, { ItemId: "H-99", Qty: 1, Price: 29.99 }) |
| |
| 3. UPDATE SPECIFIC ROW(S): |
| UpdateIf(colOrderItems, ItemId = "H-99", { Qty: 3 }) |
| |
| 4. REMOVE ITEM: |
| Remove(colOrderItems, ThisItem) |
| |
| 5. BATCH SUBMIT TO DATAVERSE: |
| ForAll(colOrderItems, Patch(OrderDetails, Defaults(OrderDetails), { ...}))|
+-----------------------------------------------------------------------------+
Core Collection Functions
| Function | Syntax | Operational Purpose |
|---|---|---|
ClearCollect | ClearCollect(CollectionName, Item1, [Item2, ...]) | Clears all existing rows from the collection and inserts the new records or table. |
Collect | Collect(CollectionName, Item1, [Item2, ...]) | Appends one or more rows to the existing collection without deleting current data. |
Clear | Clear(CollectionName) | Empties the collection completely, leaving a schema with 0 rows. |
Remove | Remove(CollectionName, Record1, [Record2, ...]) | Removes specific row records from the collection. Inside a gallery, use Remove(colData, ThisItem). |
RemoveIf | RemoveIf(CollectionName, ConditionFormula) | Evaluates a condition against every row and deletes all matching records (e.g., RemoveIf(colCart, Quantity <= 0)). |
UpdateIf | UpdateIf(CollectionName, ConditionFormula, { Field: NewVal }) | Finds all rows satisfying the condition and modifies the specified column values. |
Patch | Patch(CollectionName, TargetRecord, { Field: NewVal }) | Modifies an existing row or inserts a new row using Defaults(CollectionName). |
Batch Submitting Collections to Dataverse
Collections are frequently used to stage line items (e.g., invoice lines, time sheet entries, inspection checklists) locally before committing them in bulk to Dataverse:
// Submitting an entire collection of line items to Dataverse
ForAll(
colOrderLines As LineItem,
Patch(
OrderLines,
Defaults(OrderLines),
{
'Order Header': gblNewOrderHeaderRecord,
Product: LookUp(Products, ProductId = LineItem.ProductId),
Quantity: LineItem.Qty,
UnitPrice: LineItem.Price,
ExtendedAmount: LineItem.Qty * LineItem.Price
}
)
);
Clear(colOrderLines);
Notify("All order lines successfully submitted!", NotificationType.Success);
5. Offline Caching with SaveData, LoadData & ClearData
For canvas apps deployed to mobile frontline workers (field technicians, warehouse operators, pipeline inspectors) operating in low-connectivity or air-gapped environments, Power Apps enables manual offline caching.
+-----------------------------------------------------------------------------+
| OFFLINE DATA CACHING LIFECYCLE |
| |
| [APP STARTUP] |
| | |
| v |
| If(Connection.Connected, |
| // ONLINE: Refresh from Dataverse & Cache Locally |
| ClearCollect(colWorkOrders, Filter(WorkOrders, Owner = User().Email));|
| SaveData(colWorkOrders, "LocalWorkOrdersCache"), |
| // OFFLINE: Load from Device Encrypted Sandbox Storage |
| LoadData(colWorkOrders, "LocalWorkOrdersCache", true) |
| ) |
| |
| [OFFLINE EDITS] |
| Technician modifies records in colWorkOrders -> SaveData(colWorkOrders, ..)|
| |
| [RECONNECTION EVENT (Connection.Connected = true)] |
| Iterate through offline queue -> Patch to Dataverse -> Clear offline queue|
+-----------------------------------------------------------------------------+
Caching Functions
SaveData(CollectionName, "CacheKeyName"): Serializes an in-memory collection and writes it to encrypted local sandbox storage on iOS, Android, or Windows Power Apps mobile player.LoadData(CollectionName, "CacheKeyName", [IgnoreNonexistentFile]): Reads the serialized data from device storage and reconstructs the collection in memory. SettingIgnoreNonexistentFiletotrueprevents errors on initial app launch before a cache file has been created.ClearData("CacheKeyName"): Purges the specified local cache file from device storage.
Detecting Connectivity
Connection.Connected: Returns a boolean (trueif connected to network,falseif disconnected).Connection.Metered: Returns a boolean (trueif connected via a metered cellular connection, allowing apps to defer heavy media downloads).
[!WARNING] Platform Restriction:
SaveData()andLoadData()operate inside the Power Apps Mobile Player on mobile devices and the Windows desktop player. They do not persist data when running inside standard web browsers in Power Apps Studio preview.
An organization is deploying a mobile canvas app for field auditors who frequently operate in remote basements without internet connectivity. When the app starts, it must check if the device is connected to the internet. If offline, it must load the cached audits from the device's local storage without generating an error if no cache exists yet. Which formula correctly implements this requirement?
A consultant wants to store the logged-in user's department and manager name in memory when the app opens so that any screen in the application can reference these values without re-querying Office 365 Users on each screen. Which state container should the consultant use?
A functional consultant is designing a multi-step inspection wizard in a Canvas app across four different screens. On Screen 1, the user enters basic site details. On Screen 2, the user selects equipment. On Screen 3, the user completes an inspection checklist. On Screen 4, the user reviews a summary of all answers and submits. The data collected on Screens 1, 2, and 3 must be visible and editable on Screen 4. Which state management approach is most appropriate?
A canvas app used by field service engineers must allow engineers to add multiple replacement parts to a repair ticket before submitting the ticket. The engineer must be able to view the running list of parts, update the quantity of any part, or delete a part from the list before final submission. Which Power Fx function should the consultant use to remove a specific selected part from the local in-memory list?