This is Part 3 of the series, covering gallery design, error-handling, performance optimization, code readability, and conclusion.
Gallery Design Guidelines
Optimize galleries for performance and user experience.
Design Empty States
Show why gallery is empty and next actions.
Empty States ExamplesReset The Gallery Scroll Position
Use Reset in OnHidden to show top item.
powerapps// OnHidden property of a screen Reset(GalleryName);
Refresh To Show Current Data
Auto-refreshes for local/first load/CRUD. Manual refresh for cloud without CRUD.
Provide manual refresh button.
Refresh Button ExampleFilter Large Datasets
Support multiple field filters.
Filter Dropdowns Examplepowerapps// ITEMS property of a gallery with three dropdowns filters Filter( 'Paid Time Off', drp_Type.Selected.Value=Blank() Or TimeOffType=drp_Type.Selected.Value, drp_Status.Selected.Value=Blank() Or Status=drp_Status.Selected.Value, drp_Employee.Selected.Value=Blank() Or Employee=drp_Employee.Selected.Value )
Define The Sort Order
Sort by title (asc) or date (desc); indicate if other.
Sorted Gallery ExampleDo Not Show Live Updates for Search Results
Use button for search to avoid performance issues.
powerapps// Items property of a searchable gallery connected to a text input Search(Locations, txt_SearchLocation.Text, "Address", "City", "Province")
Instead:
powerapps// OnSelect property of a search button Set(gblSearchLocation, txt_SearchLocation.Text) // Items property of a searchable gallery using a global variable Search(Locations, gblSearchLocation, "Address", "City", "Province")
Avoid Nested Galleries
Use collections for grouped data to avoid slowdowns.
Nested Gallery ExampleUse Flexible Height Galleries
Prefer flexible height over blank vertical for consistent properties.
Gallery TypesError-Handling
Robust error-handling prevents crashes and improves UX.
Enable Formula-Level Error Management
Turn on in advanced settings for IfError, IsError, OnError.
Error Management SettingPatch Function Error-Handling
Wrap in IsError; notify on failure.
powerapps// create a new invoice If( IsError( Patch( 'Invoices', Defaults('Invoices'), { CustomerNumber: "C0001023", InvoiceDate: Date(2022, 6, 13), PaymentTerms: "Cash On Delivery", TotalAmount: 13423.75 } ) ), // on failure Notify("Error: the invoice could not be created", NotificationType.Error), // on success Navigate('Success Screen') )
Power Apps Forms Error-Handling
Use OnSuccess/OnFailure; avoid code after SubmitForm.
powerapps// OnSelect property of the form's submit button SubmitForm(frm_Invoice) // OnSuccess property of the form Navigate('Success Screen'); // OnFailure property of the form Notify( "Error: the invoice could not be created", NotificationType.Error ) // Bad: OnSelect property of the form's submit button SubmitForm(frm_Invoice) Navigate('Success Screen');
Power Automate Flow Error-Handling
Check response with IsError.
powerapps// Get customer invoices If( IsError( GetAllCustomerInvoices.Run("C0001023") ), // On failure Notify("Error: could not retrieve customer invoices", NotificationType.Error), // On success Navigate('Success Screen') )
Use IfError for calculations.
powerapps// calculate the percentage of tasks completed IfError( gblTasksCompleted/gblTasksTotal, 0 )
Handling Unexpected Errors
Use OnError for unhandled errors; notify or log.
powerapps// unexpected error notification message Notify( Concatenate( "Error: " , FirstError.Message, "Kind: ", FirstError.Kind, ", Observed: ", FirstError.Observed, ", Source: ", FirstError.Source ), NotificationType.Information );
For production, use Trace with Azure Application Insights.
Optimizing App Performance
Enhance speed and efficiency.
Load Multiple Datasets Concurrently
Use Concurrent for parallel cloud calls.
powerapps// Sequential code execution (slower) Set( gblUserProfile, Office365Users.GetUserProfileV2(User().Email) ); ClearCollect( colActiveProjects, Filter( Projects, ProjectStatus.Value="Active" ) ) // Simultaneous code execution (faster) Concurrent( // Thread #1 Set( gblUserProfile, Office365Users.GetUserProfileV2(User().Email) ), // Thread #2 ClearCollect( colActiveProjects, Filter( Projects, ProjectStatus.Value="Active" ) ) )
Write Formulas That Use Delegation
Delegate operations to cloud for efficiency.
A warning appears for non-delegable functions.
Use Dataverse views to bypass delegation limits.
powerappsFilter( 'Device Orders', 'Device Orders (Views)'.'Active Device Orders' )
Delegation WarningCache Data in Collections and Variables
Store frequent data locally.
powerapps// Store the currency exchange rates table in memory for quicker access ClearCollect( colCurrencyExchangeRates, 'Currency Exchange Rates' )
Limit The Size of Collections
Select minimal rows/columns; use ShowColumns, explicit column selection.
powerapps// selecting only desired columns from the accounts table ClearCollect( colAccounts ShowColumns( Accounts, "name", "city", "state", "zipcode" ) )
"Batch Patch" Multiple Changes to a data source Table at Once
Use Patch with table for simultaneous updates.
powerapps// collection of records to update ClearCollect( colUpdateEmployees, Table( {ID: 2, FullName: "Alice Henderson", Active: true}, {ID: 4, FullName: "David Wright", Active: false}, {ID: 5, FullName: "Mary Allen", Active: false} ) ); // update records one-by-one (slower) ForAll( colUpdateEmployees, Patch( Employees, LookUp(Employees, ID=colUpdateEmployees[@ID]), { FullName: colUpdateEmployees[@FullName], Active: colUpdateEmployees[@Active] } ) ); // bulk update multiple records at once (faster) Patch( Employees, ShowColumns( colUpdateEmployees, "ID", "FullName", "Active" ) );
Reduce Code in The On Start Property
Defer to OnVisible for faster startup.
Monitor "Time to first screen" in Analytics.
Performance AnalyticsMinimize Number of Controls On A Single Screen
Use galleries for repetition; split screens if needed.
Gallery for Repetitive ControlsEnable DelayOutput For Text Input Controls
Delay updates for search bars.
DelayOutput SettingDo Not Reference Controls On Other Screens
Use variables to avoid loading unused screens.
Improving Code Readability
Make code easier to understand and maintain.
Apply Automatic Formatting
Use "Format text" for consistent style.
Format Text ButtonUse The WITH Function To Improve Readability
Break complex formulas.
powerappsValue(txt_InterestRate.Text)/100 * Value(txt_LoanAmount.Text) / (1 - (1 + Value(txt_InterestRate.Text)/100)^-Value(txt_NumberOfPayments.Text))
Vs.
powerappsWith( { InterestRate: Value(txt_InterestRate.Text)/100, LoanAmount: Value(txt_LoanAmount.Text), NumberOfPayments: Value(txt_NumberOfPayments.Text) }, InterestRate * LoanAmount / (1 - (1 + InterestRate)^-NumberOfPayments) );
Choose Consistent Logical Operators
Stick to one style for And/Or.
powerappsClearCollect( colCustomers, {State: "NY", Status: "Active"} ); // And operator Filter( colCustomers, State = "NY" And Status="Active" ); // And() function Filter( colCustomers, And( State = "NY", Status="Active" ) ); // && operator Filter( colCustomers, State = "NY" && Status="Active" )
Join Text Strings & Variables
Consistent method: &, Concatenate, or $-strings.
powerapps// set variables Set(gblUserName, User().FullName); Set(gblStreetAddress, "123 Chestnut Street"); // join text using the & operator "Hi, my name is"&gblUserName&" and I live at "&gblStreetAddress&"."; // join text using the Concatenate function Concatenate("Hi, my name is", gblUserName,"and I live at ",gblStreetAddress)&"."; // join text using $-Strings $"Hi, my name is {gblUserName} and I live at {gblStreetAddress}"
Remove IF Statements When The Result Is A True Or False Value
Use direct logical.
powerapps// With IF Statement evaluates to true or false If(gblUserRole="Manager" And gblIsDataLoaded=true, true, false) // Without IF Statment evaluates to true or false gblUserRole="Manager" And gblIsDataLoaded
Substitute The Self Operator for The Current Control Name
Shorter references.
powerapps// Reference using the current control name ColorFade(txt_SubmitForm.Fill, -10%) // Reference using the Self operator ColorFade(Self.Fill, -10%)
Flatten Nested IFs
Avoid deep nesting.
powerappsSet(gblBankAccountBalance, 5000); Set(gblDailyWithdrawlLimit, 1000); Set(gblWithdrawlAmount, 100); // Nested IFs If( gblWithdrawlAmount > gblBankAccountBalance, Notify("Insufficent funds", NotificationType.Error), If( gblWithdrawlAmount > gblDailyWithdrawlLimit, Notify("Daily withdrawl limit exceeded", NotificationType.Error), Notify("You have Withdrawn $"&gblWithdrawlAmount, NotificationType.Success) ) ); // Flattened IFs If( gblWithdrawlAmount > gblBankAccountBalance, Notify("Insufficent funds", NotificationType.Error), gblWithdrawlAmount > gblDailyWithdrawlLimit, Notify("Daily withdrawl limit exceeded", NotificationType.Error), Notify("You have withdrawn $"&gblWithdrawlAmount, NotificationType.Success) );
Alphabetical Order in Patch & UpdateContext Functions
Easier to find fields.
powerapps// create a new record Patch( colContacts, Defaults(colContacts), { Active: true, Address: "67 Walnut Grove", Name: "Jane Smith", PostalCode: "R2G 3V3", Province: "Ontario" } ); // update local variables UpdateContext( { locAccountID: GUID(), locBlockerUserInput: true, locIsMenuVisible: false, locReadOnlyMode: false, locSelectedProperty: "Location" } );
Simplify Logical Comparisons When Evaluating a Boolean
Use Boolean directly.
powerappsSet(gblIsBankAccountActive, true); // logical comparison If( gblIsBankAccountActive=true, Navigate('Withdraw Funds Screen'), Notify("Bank account is not active", NotificationType.Error) ); // boolean value only If( gblIsBankAccountActive, Navigate('Withdraw Funds Screen'), Notify("Bank account is not active", NotificationType.Error) )
Handle Errors Gracefully
Implement robust error checks and user notifications to prevent crashes and data loss.
Keep It Simple and Efficient
Follow KISS principles, use modern features, and refactor regularly.
"Well-formatted code has two benefits. It is easier to read and quicker to spot mistakes." - Power Apps Coding Standards
Best Practices for Power Apps Development
- Delegation and Performance: Always delegate where possible.
- Error Management: Enable formula-level handling.
- Theming Consistency: Use variables or templates.
- Code Readability: Format, flatten, and simplify.
- Testing: Use tools, peers, and UAT.
Continuous Improvement
Stay updated with Power Apps releases, participate in reviews, and refine skills through practice.
Mastering these standards elevates Power Apps development. For full details, refer to the official Power Apps documentation.