Most Power Apps tutorials stop at building the form — this lesson finishes the job. Learn how to wire up SubmitForm and Patch to actually save data, handle success and failure with Notify, and reset forms cleanly so users always know their data went through.

You've built the form. Your users can type in their names, select from dropdowns, and fill out every field. But what happens when they click that Submit button? If you've ever watched a user tap a button and then stare blankly at the screen wondering whether anything actually happened — wondering if their data was saved, lost, or floating in digital limbo — you already understand the problem this lesson solves.
Data entry without a complete submission loop is broken data entry. The form is only half the equation. The other half is what happens the moment a user clicks Submit: the data travels to its destination, the app confirms success, and the user knows exactly what to do next. Getting that loop right is the difference between an app that feels professional and one that feels like a prototype.
By the end of this lesson, you'll be able to wire up a Submit button that actually saves data to a data source, handle both the SubmitForm function and the Patch function (and know when to use each), display a meaningful success notification to the user, and reset the form cleanly so it's ready for the next entry. This is the skill that transforms a pretty interface into a working business tool.
What you'll learn:
You should be comfortable with the Power Apps canvas editor and know how to add controls to a screen. If you've followed along with Build Your First Canvas App in Power Apps or Your First Power App: Build a Data Entry Form in 30 Minutes, you're in exactly the right place. You should also have a data source connected — SharePoint, Dataverse, or Excel. If you need to set one up, Connecting Power Apps to SharePoint, Excel, and Dataverse: A Complete Integration Guide will walk you through it.
Before we touch the Submit button, we need to understand what the EditForm control is doing behind the scenes. Think of an EditForm as a smart container. It knows which data source it's connected to, it keeps track of every field your user has touched, and it bundles all of those values into a single record — ready to be written to your data source the moment you tell it to.
When you place an EditForm on a screen and connect it to a SharePoint list (or any other data source), Power Apps automatically generates DataCard controls for each column in that list. Each DataCard contains an input control — a text input, a dropdown, a date picker — and each input control has a property called Default that reads from the current record. When your user types something, that value gets stored inside the form's temporary state.
The important thing to understand is that until you explicitly submit the form, none of that data has gone anywhere. The values live inside the EditForm control, not in your data source. The form is like a staging area.
Key insight
The EditForm control doesn't save anything automatically. It holds your user's input in memory until you call SubmitForm. This is intentional — it gives you the chance to validate, confirm, or cancel before any data is written.
The form also has a Mode property that you should be aware of. It can be set to FormMode.New (for creating new records), FormMode.Edit (for updating an existing record), or FormMode.View (read-only). You set this explicitly, and it controls whether SubmitForm creates a new row or updates an existing one.
SubmitForm is the function designed to work hand-in-hand with the EditForm control. When you call it, Power Apps takes every DataCard's value from the form, bundles them into a record, and writes that record to your connected data source. If the form is in FormMode.New, it creates a new row. If it's in FormMode.Edit, it updates the existing row.
Here's the basic setup. First, make sure your EditForm is named — let's call ours FormProjectRequest. Now add a Button control to the screen. Set the button's Text property to "Submit". Then set its OnSelect property to:
SubmitForm(FormProjectRequest)
That's the minimum viable submission. But stopping here leaves a gap — your user has no idea whether it worked.
The EditForm control exposes two special properties: OnSuccess and OnFailure. These fire automatically after SubmitForm runs, depending on the outcome. This is where you add your user feedback.
Click on your EditForm control and find the OnSuccess property in the formula bar. Set it to:
Notify(
"Your request was submitted successfully!",
NotificationType.Success
);
ResetForm(FormProjectRequest);
Navigate(HomeScreen, ScreenTransition.Fade)
And set the OnFailure property to:
Notify(
"Something went wrong. Please try again or contact support.",
NotificationType.Error
)
Let's walk through what each line is doing.
Notify is a function that displays a banner message at the top of the app. The first argument is the message text. The second argument is the type of notification, which controls the color and icon of the banner. NotificationType.Success renders a green banner. NotificationType.Error renders a red one. You can also use NotificationType.Warning and NotificationType.Information.
ResetForm clears all the user's input and returns the form to its default state. Without this, the old values would still be sitting in the form fields the next time the user sees that screen — confusing and potentially dangerous.
Navigate sends the user to a different screen after a successful save. This is optional but often the right UX choice. If your form is part of a multi-screen app, you probably want to send users back to a list or home screen after submission. You can learn more about structuring this in Building Multi-Screen Apps with Navigation and Variables in Power Apps.
Tip
Always pair SubmitForm with both OnSuccess and OnFailure handlers. An app that silently fails is worse than one that visibly errors — at least your user knows something went wrong.
SubmitForm is elegant when you're working with an EditForm control. But sometimes you don't want to use an EditForm at all. Maybe you're collecting data from individual Text Input controls scattered across the screen, or you need to save a record programmatically based on some calculated values. In those cases, the Patch function is your tool.
Patch writes a record directly to a data source without needing a form container. Here's the basic syntax:
Patch(
DataSourceName,
BaseRecord,
ChangeRecord
)
Defaults(DataSourceName) to create a new record, or use an existing record to update it.Imagine you're building a project intake form. You have three Text Input controls on the screen: InputProjectName, InputRequestor, and InputDepartment. You also have a Dropdown called DropdownPriority. Your SharePoint list is called ProjectRequests.
Here's the OnSelect formula for your Submit button:
Patch(
ProjectRequests,
Defaults(ProjectRequests),
{
Title: InputProjectName.Text,
Requestor: InputRequestor.Text,
Department: InputDepartment.Text,
Priority: DropdownPriority.Selected.Value,
SubmittedDate: Today()
}
)
Notice that we're also writing SubmittedDate: Today() — something the user never fills in. Patch lets you include calculated or system-generated values alongside user input. SubmitForm doesn't give you this level of precision without extra workarounds.
Warning
Column names in your Patch record must match the internal column name in your data source, not necessarily the display name. In SharePoint, for example, a column displayed as "Project Name" might have an internal name of "Project_x0020_Name". Use the internal name in your formula or the Patch will silently skip that field.
Unlike SubmitForm, Patch doesn't have OnSuccess and OnFailure hooks. Instead, you need to handle errors inline using IfError. Here's how to do that:
IfError(
Patch(
ProjectRequests,
Defaults(ProjectRequests),
{
Title: InputProjectName.Text,
Requestor: InputRequestor.Text,
Department: InputDepartment.Text,
Priority: DropdownPriority.Selected.Value,
SubmittedDate: Today()
}
),
Notify(
"Failed to save your request: " & FirstError.Message,
NotificationType.Error
),
Notify(
"Request submitted successfully!",
NotificationType.Success
);
Reset(InputProjectName);
Reset(InputRequestor);
Reset(InputDepartment);
Navigate(HomeScreen, ScreenTransition.Fade)
)
IfError takes up to three arguments: the expression to try, what to do if it errors, and what to do if it succeeds. Notice that on success, we call Reset() on each individual input control rather than ResetForm() — because without a form container, there's no form to reset. You call Reset() once per control.
Also note FirstError.Message — this is a Power Apps record that's automatically populated when an error occurs inside an IfError block. Surfacing the actual error message in your Notify helps users (and you, during debugging) understand what went wrong. For a deeper treatment of resilient error handling patterns, see Canvas App Error Handling: Building Resilient Apps with IfError, Notify, and Graceful Failure Patterns.
Before you even attempt to write anything to your data source, you should verify that the user has actually filled in what's required. Submitting a record with a blank Title field only to have it fail at the data source level — and then trying to decode an error message — is a poor experience.
The right approach is to validate in the button's OnSelect before calling SubmitForm or Patch. Here's a simple guard using If and IsBlank:
If(
IsBlank(InputProjectName.Text) || IsBlank(InputRequestor.Text),
Notify(
"Please fill in all required fields before submitting.",
NotificationType.Warning
),
Patch(
ProjectRequests,
Defaults(ProjectRequests),
{
Title: InputProjectName.Text,
Requestor: InputRequestor.Text,
Department: InputDepartment.Text,
Priority: DropdownPriority.Selected.Value,
SubmittedDate: Today()
}
)
)
The || operator means "or" — so this reads: "If the project name is blank OR the requestor is blank, show a warning. Otherwise, run Patch."
Note
If you're using the EditForm control, Power Apps has a built-in mechanism for required fields — you can mark a DataCard as Required, and SubmitForm will refuse to submit (and will highlight the missing fields in red) if any required fields are empty. This is another advantage of using the EditForm + SubmitForm approach for standard forms. For deeper validation logic, check out Power Apps Data Validation: Using If, IsBlank, and IsMatch to Prevent Bad Data in Forms.
Now that you've seen both approaches, let's be direct about when to use each.
Use SubmitForm when:
Use Patch when:
User(), calculated fields) alongside user inputKey insight
Many real-world apps use both. An EditForm handles the user-visible fields, and a Patch call inside OnSuccess adds system metadata like SubmittedBy: User().Email or SubmittedDate: Now() to the same record immediately after the form saves. The two approaches complement each other.
The Notify function is powerful but easy to under-use. A generic "Success!" message is fine, but a message that reflects what just happened is much better.
Compare these two:
Notify("Saved!", NotificationType.Success)
versus:
Notify(
"Project request for '" & InputProjectName.Text & "' submitted. Someone will reach out within 2 business days.",
NotificationType.Success
)
The second one echoes back what the user just did, sets expectations, and feels responsive. If your data source returns the new record's ID after a Patch, you can even include that:
Set(
varNewRecord,
Patch(
ProjectRequests,
Defaults(ProjectRequests),
{ Title: InputProjectName.Text }
)
);
Notify(
"Request #" & Text(varNewRecord.ID) & " submitted successfully.",
NotificationType.Success
)
Here we're using Set to capture the return value of Patch — which is the full record that was written, including any server-generated values like the ID. We then reference that record's ID in the notification. This is a pattern that immediately feels professional to end users. To understand how variables like varNewRecord work in Power Apps, see Power Apps Variables Explained: When to Use Global Variables, Context Variables, and Collections in Canvas Apps.
Let's put everything together in a single exercise. You'll build a functional project intake form that saves to a SharePoint list and gives users clear feedback.
Setup:
Create a SharePoint list called ProjectRequests with the following columns: Title (single line of text), Requestor (single line of text), Priority (choice: Low / Medium / High), and SubmittedDate (date).
In Power Apps, create a new Canvas App from blank and connect to your ProjectRequests SharePoint list.
Build the form:
Insert an EditForm control. Set its DataSource property to ProjectRequests and its DefaultMode to FormMode.New.
In the form's field editor (click "Edit fields" in the right panel), add all four fields: Title, Requestor, Priority, and SubmittedDate.
Remove the SubmittedDate DataCard from the form — you'll populate this automatically.
Wire up the Submit button:
Add a Button control below the form. Set its Text to "Submit Request".
Set the button's OnSelect to:
SubmitForm(FormProjectRequest)
OnSuccess property to:Patch(
ProjectRequests,
Last(
Filter(
ProjectRequests,
Requestor = InputRequestor.Text
)
),
{ SubmittedDate: Today() }
);
Notify(
"Your project request has been submitted! Expect a response within 3 business days.",
NotificationType.Success
);
ResetForm(FormProjectRequest)
OnFailure property to:Notify(
"Submission failed: " & FormProjectRequest.Error.Message,
NotificationType.Error
)
Test it:
Press F5 (or click the Play button) to preview the app. Fill in the Title and Requestor fields, choose a Priority, and click Submit Request. You should see the green success banner and the form should clear itself.
Switch to your SharePoint list and refresh it — your record should be there, with SubmittedDate populated.
Tip
If you're not seeing the record appear, check the Requestor field value and make sure the column names in your Patch formula match the internal SharePoint column names exactly. The SharePoint Title column is always safe — all other columns should be verified in the SharePoint list settings.
The form submits but nothing appears in the data source. Most often this is a permissions issue or a column name mismatch. Verify that the account running the app has write access to the SharePoint list. Then check that every column name in your Patch or DataCard maps to an actual column in the source.
OnSuccess fires but the form still shows old data.
You called SubmitForm but forgot to call ResetForm. Add ResetForm(YourFormName) to your OnSuccess handler.
SubmitForm doesn't seem to do anything when I click the button.
Make sure the button's OnSelect calls SubmitForm(FormName) with the correct form name. Open the Tree View (the left panel showing all controls) and verify the EditForm's exact name — it's case-sensitive in formulas.
The Notify message shows but the Patch fails silently.
You may be writing to a column that doesn't exist, or writing a value with the wrong type. Wrap your Patch in IfError and display FirstError.Message to see exactly what Power Apps is rejecting.
The form keeps submitting duplicate records.
This usually happens when users click Submit multiple times before the save completes. Disable the button during submission by setting its DisplayMode property to: If(FormProjectRequest.Loading, DisplayMode.Disabled, DisplayMode.Edit). The Loading property on the EditForm is true while SubmitForm is in progress.
Warning
Never chain multiple SubmitForm calls or call SubmitForm inside a ForAll loop. SubmitForm is designed for single-record operations. If you need to write multiple records at once, use Patch inside a ForAll, or look into Canvas App Bulk Data Operations for the right patterns.
You now have a complete picture of the data entry loop in Canvas Apps. The submit button isn't just a button — it's the trigger for a sequence: validate the data, write it to a source, confirm success or surface failure, notify the user, and reset the state. Getting each of those steps right is what makes an app trustworthy enough for real business use.
Here's what you've mastered:
From here, you'll want to go deeper on a few natural extensions. If your form has complex validation rules — email format checking, numeric range validation, conditional required fields — Power Apps Data Validation: Using If, IsBlank, and IsMatch to Prevent Bad Data in Forms covers that territory thoroughly. If you're building an app with multiple screens and you need form data to flow between them, Building Multi-Screen Apps with Navigation and Variables in Power Apps is your next read. And if you want to understand how forms behave under the hood with galleries and more complex layouts, Power Apps Controls: Galleries, Forms, and Data Tables - Advanced Architecture and Performance will take you further.
The data entry loop is now closed. What happens after the save is up to you.