2 min read

Use Context Variables to Simplify Multi-Step Power Apps Logic

Use context variables in Power Apps to break complex logic into manageable steps. Track progress, handle errors, and keep your code readable.
A simple form with three fields we're saving to SharePoint.

Some logic requires multiple steps, such as validation and saving to multiple data sources.

Instead of nested if statements, I prefer to set a local variable named continue. At the end of each step, we set continue to true if the step was successful, or false if it wasn’t.

Each step runs only if continue is true, ensuring we don’t run logic after a step fails. If you want to get fancy, you could revert the changes if a step fails, setting everything back to the original state, similar to SQL Transactions.

In this example formula, we validate the data, then save it to SharePoint. If that succeeds, we send a notification, then clean up and notify the user that it was successful.

If the validation fails, we never try to save to SharePoint. If the save to SharePoint fails, we never try to send the notification.

Importantly, we’re not using nested if statements for our logic, making this code easier to read.

// 1. When clicked, this button will first validate all of the fields on the form are valid.
// 2. Then it will save the values from the form to the SharePoint list.
// 3. Finally, it will send notifications if the save was successful.
// Set our initial local context variables.
UpdateContext(
    {
        continue: true,
        status: "Starting Validation"
    }
);
// Validate that the fields are valid.
If(
    Or(
        txtTextField.ValidationState = "Invalid",
        numNumberField.ValidationState = "Invalid",
        dteDateField.ValidationState = "Invalid"
    ),
    Notify(
        "Please correct all of the fields highlighted in red.",
        NotificationType.Warning
    );
    UpdateContext({continue: false}),
    UpdateContext({continue: true})
);
// Save the data to SharePoint
If(
    continue,
    UpdateContext({status: "Saving"});
    UpdateContext(
        {
            tmpSaveResult: Patch(
                'Demo SharePoint List',
                Defaults('Demo SharePoint List'),
                {
                    Title: txtTextField.Value,
                    'Date Field': dteDateField.SelectedDate,
                    'Number Field': numNumberField.Value
                }
            )
        }
    );
    IfError(
        tmpSaveResult,
        Notify(
            FirstError.Message,
            NotificationType.Error
        );
        UpdateContext({continue: false});
        Trace(
            FirstError.Message,
            TraceSeverity.Error,
            {
                Message: FirstError.Message,
                Source: FirstError.Source,
                User: User().Email,
                txtTextField: txtTextField.Value,
                dteDateField: dteDateField.SelectedDate,
                numNumberField: numNumberField.Value
            }
        ),
        UpdateContext({continue: true})
    )
);
// Execute any next steps (send a notification, save other data, etc.)
If(
    continue,
    true,
    false
);
// Clean Up
If(
    continue,
    Notify(
        "Success",
        NotificationType.Success
    );
    UpdateContext(
        {
            continue: false,
            status: Blank()
        }
    )
)

If an error occurs in the Patch, we catch it and return an error message to the user, while also logging the error using a Trace. If our app is connected to Azure Application Insights, we'll see this error logged there.

A screenshot of an error when saving to SharePoint.