Elevate Your Power Apps Code: A Guide to Cleaner Formulas and Better Maintenance
Learn how small coding practices—like using descriptive names, flattening conditions, and simplifying logic—can make your apps easier to update and less error-prone.
Welcome to a practical exploration of coding style in Power Apps. You've probably written formulas that seemed clever in the moment but became puzzling a week later. Clean code is not about perfection; it's about clarity and maintainability. Rather than listing abstract tips, I'll walk through a concrete example—a task dashboard—and show how each improvement makes the formulas easier to read and change. By the end, you'll have a checklist you can use on your next project.
The Scenario: A Task Health Dashboard
Imagine you're building a canvas app connected to a SharePoint list named ProjectTasks. The list includes these columns:
| Display Name | Internal Name | Type |
|---|---|---|
| Task Title | Title | Text |
| Owner | Owner | Person |
| Deadline | Deadline | Date/Time |
| Urgency | Urgency | Choice: High, Medium, Low |
| Progress % | ProgressPct | Number (0–100) |
| State | State | Choice: Not Started, In Progress, Completed |
You need a gallery that shows each task with a health indicator: Green (on track), Yellow (at risk), or Red (delayed). The business rules:
- If a task is in the Completed state, health is always Green.
- If the deadline has passed and the task isn't completed, health is Red.
- For urgent tasks (High urgency) that are less than 50% done, health is Yellow.
- Otherwise, health is Green.
The rest of the article uses this scenario to demonstrate ten code style refinements.
Simplify Complex Expressions with With
The With function lets you define temporary named values, reducing repetition and clarifying intent. Compare these two versions of the health calculation.
If(
ThisItem.State = "Completed",
"Green",
If(
ThisItem.Deadline < Today(),
"Red",
If(
ThisItem.Urgency = "High" && ThisItem.ProgressPct < 50,
"Yellow",
"Green"
)
)
)With Named Variables
With(
{
taskState: ThisItem.State,
deadline: ThisItem.Deadline,
progress: ThisItem.ProgressPct,
urgency: ThisItem.Urgency
},
If(
taskState = "Completed",
"Green",
If(
deadline < Today(),
"Red",
If(
urgency = "High" && progress < 50,
"Yellow",
"Green"
)
)
)
)The second formula still uses nested IFs (we'll address that next), but the With block already makes it easier to see which column each condition refers to.
Flatten Conditional Logic with Switch
Deep chains of If functions are hard to read and debug. A Switch with a first argument of true replaces a series of If conditions with a flat list.
Switch( true, ThisItem.State = "Completed", "Green", ThisItem.Deadline < Today(), "Red", ThisItem.Urgency = "High" && ThisItem.ProgressPct < 50, "Yellow", "Green" )
This version not only looks cleaner but also makes it trivial to add or reorder conditions. Use the Format text command (right‑click in the formula bar) to apply consistent indentation automatically.
Write Comments That Add Value, Not Noise
Comments should explain why you're doing something, not what you're doing. The code itself should already show the what.
// Good: Explains the business rule behind the health colours Switch( true, ThisItem.State = "Completed", "Green", ThisItem.Deadline < Today(), "Red", ThisItem.Urgency = "High" && ThisItem.ProgressPct < 50, "Yellow", "Green" ) // Avoid: Stating the obvious // If the task state is "Completed" then set the colour to "Green" Switch( ... )
Use line comments (//) for short notes and block comments (/* ... */) for longer explanations. Remember to update comments when the logic changes—stale comments are worse than none.
Simplify Boolean Checks
When a condition already yields a boolean, there's no need to wrap it in If.
Unnecessary IF Removal
// Before If(ThisItem.State = "Completed", true, false) // After ThisItem.State = "Completed"
You can use the simplified version directly in a control's Visible property, for example.
Similarly, avoid redundant comparisons on boolean variables:
// Instead of If(varIsEditable, true, false) // Use varIsEditable
Use the Self Operator for Conciseness
Inside a control's property, the Self operator refers to that control. It saves typing and avoids confusion when you rename the control.
Self.Text = "abc"; // Sets the value of the current text input // Instead of TextInput1.Text = "abc"; // Which control is TextInput1?
Be cautious when using Self in galleries: in gallery templates, Self refers to the gallery itself, not the individual control inside it. In that case, use ThisItem or the control's own name.
Pick One Way to Build Strings
Power Apps offers the & operator, the Concatenate function, and $-Strings ($"..."). Choose one—preferably & for its simplicity—and stick to it.
// Using & (recommended)
$"{txtUserName.Text} has {taskCount} tasks"
// In code use &
"Assigned: " & ThisItem.Owner.DisplayName & " | State: " & ThisItem.StateIf you use $-Strings, be aware that inside a code editor that uses backticks (like this one) you may need to escape characters. For consistency, the examples in this article use &.
Choose a Logical Operator and Be Consistent
The logical AND can be written as And (function), And() (shorthand), or &&. Pick one and apply it everywhere. && is the most concise and widely recognised.
// Use && consistently If(ThisItem.Urgency = "High" && ThisItem.ProgressPct < 50, "Yellow", "Green") // Avoid mixing If(ThisItem.Urgency = "High" And ThisItem.ProgressPct < 50, ...)
The same principle applies to Or and || and Not with !.
Alphabetize Arguments in Patch and UpdateContext
When Patch or UpdateContext contain many fields, an alphabetical order helps you locate a field quickly without scanning the whole list.
Patch(
ProjectTasks,
galTasks.Selected,
{
Deadline: dpDeadline.SelectedDate,
Owner: cmbOwner.Selected.User,
ProgressPct: sldProgress.Value,
State: ddState.Selected.Value,
Title: txtTitle.Text,
Urgency: ddUrgency.Selected.Value
}
)Apply the same idea to UpdateContext:
UpdateContext({
ctxCurrentState: "In Progress",
ctxProgress: 75,
ctxTaskTitle: "Design review"
})Common Mistakes and Troubleshooting
- Stale comments: When you update logic, immediately update the associated comment. Otherwise, the comment will mislead the next developer (or your future self).
- Inconsistent naming: Mixing conventions like
lbl_FirstName,Lbl_FirstName, andlabelFirstnamecreates confusion. Agree on a prefix system (e.g.,lbl,txt,gal) before you start. - Deeply nested IFs: They are the number one source of logic bugs. Refactor to
Switchor a flat sequence ofIfs as early as possible. - Ignoring the format command: The formula bar's Format text (right‑click) is a one‑click way to align indentation and line breaks. Use it before closing a property.
Troubleshooting tip: When a formula isn't behaving as expected, use temporary labels to display the intermediate values of With variables or the result of a Switch. This often reveals a mismatched condition.
Performance and Delegation
Clean code itself doesn't directly affect performance, but readable formulas are easier to optimise. For large data sources, always consider delegation: place conditions that filter early in the query, and use With to hold filtered tables rather than applying filters in separate steps.
Final Recommendation
Adopting these practices doesn't have to happen overnight. Start with one—such as consistent naming or flattening IFs—and gradually layer on the others. The benefits will become clear the first time you revisit a formula written weeks earlier and can understand it immediately.
References
- Original article that inspired this guide: Matthew Devaney, 10 Power Apps Code Examples To Improve Your Coding Style – https://www.matthewdevaney.com/10-power-apps-code-examples-to-improve-your-coding-style/
- Microsoft Learn:
Withfunction – [placeholder for official docs URL] - Microsoft Learn:
Switchfunction – [placeholder for official docs URL] - Microsoft Learn:
Selfoperator – [placeholder for official docs URL] - Microsoft Learn: Comments in Power Apps – [placeholder for official docs URL]