
Hello folks. I recently tackled one of these scenarios, and what seemed like a simple validation turned into a bit of a deep dive.
In this post, I’ll share how I handled preventing of form save during async operations involving subgrid data, using a real-world example from a JavaScript customization I worked on.
Example Scenario
Let’s say you have two tables:
- Order (the parent)

- Order Items (child records shown in a subgrid on the Order form)

Functionality:
-
The Order table includes a
Order Status
field (an option set with values like Open, Closed, and Cancelled).

-
Each Order Item has a boolean field called
Ready to Dispatch?
.

Here’s the condition:
If even one Order Item isn’t marked as “Ready to Dispatch,” the Order shouldn’t be allowed to close (i.e., you can’t set its Status to “Closed”). If a user tries to close the Order while there are pending items, we need to stop the form from saving and let them know.
The First Approach: Using
preventDefault()
in OnSave
Initially, I thought this would be easy. I planned to use:
-
Xrm.WebApi.retrieveMultipleRecords()
to check the subgrid data (Order Items) -
Call
eventArgs.preventDefault()
if any record didn’t meet the criteria
But there was a catch: the retrieve multiple is asynchronous. So even though the logic was correct, the form would sometimes save before the validation was done - letting invalid data slip through.
Finding the Fix: Async OnSave Handlers
Turns out, Power Apps has a way to help with this: async OnSave handlers. These let you run asynchronous logic before the form actually saves, which was exactly what I needed.
Here’s the functionality I implemented:
- Create a web resource and add it in the OnSave event handler on the Order form.
-
When the
Status
changes to "Closed" and the Save button is clicked, I trigger a validation check. -
The check:
-
Uses
Xrm.WebApi.retrieveMultipleRecords()
to fetch Order Items. -
Loops through them to see if all are
Ready to Dispatch
. -
If not, calls
preventDefault()
to block the save.
-
Uses
- To add the asynchronous function in the OnSave event handler we need to enable the Async OnSave Handler in App settings
It was working great… until I hit the next hiccup.
The Unexpected Issue: Auto-Save
If you’ve worked with Model-Driven Apps or Dynamics 365 CRM for a while, you’ll know they come with auto-save enabled by default. This means the form tries to save itself every 15–30 seconds or so.
With my validation in place, the form would now block the save and show an
error message—even when the user wasn’t doing anything. That wasn’t ideal. It
interrupted the user experience and created unnecessary confusion. so i have
used the
getSaveMode()
to check the save mode.
Smarter Handling: Using
getSaveMode()
to Detect
Auto-Save
To solve this, I turned to
eventArgs.getSaveMode()
, which
tells you how the form is being saved. You can find the values of the
getSaveMode() function from the table below.
Using this, I adjusted the logic:
-
For auto-save (
getSaveMode() === 70
): I only blocked the save quietly usingpreventDefault() -
no error message. -
For
manual save (getSaveMode() === 1 || getSaveMode() === 2):
I blocked the save and showed a proper validation message using
Xrm.Navigation.openAlertDialog()
.
- I have left one product as not ready to dispatch? (Kept as it is)

- I have changes the Order Status to "Closed" and clicked Save button.

- Even I have tested during the autosave also, the alert doesn't thrown again.
- And finally my form also doesn't got saved until the products under the same order are not in the state of ready to dispatch as true.
You can find the code for the above example use case below.
This small change made a big difference in how the app behaved and how users experienced the form.
My Learnings:
- Always use async OnSave handlers for async validations in the on save event.
- Don’t forget about auto-save, it can throw a wrench into your logic if not handled properly.
-
Use
getSaveMode()
to fine-tune your user experience and avoid unnecessary alerts.