In Dynamics 365 forms, we often run into situations where a record looks unsaved even though the user hasn’t made any manual changes. This usually happens when fields are updated in the background by scripts. When that happens, those attributes are flagged as dirty and the form behaves as if the user made edits. The result is that whenever users try to navigate away, they are interrupted by the familiar “You have unsaved changes” popup.

In our case, we were getting this issue for fields which were already hidden from the form. Also here as the record was on a particular stage, where we were setting all the fields in the form read-only, and also cancelling the save event. Because of which user was also not able to save the form.

The way we fixed this issue was to scan all the attributes on the form in onload, detect which ones are dirty and reset their submit behaviours. By setting their submit mode to “never“, these fields were not included in the save operation, and the form was now showing the saved state, thus no unsaved changes prompts.
clearAllDirtyFields: function (executionContext) {
var formContext = executionContext.getFormContext();
// Delay to allow system updates (rollups/calculated fields) to complete
setTimeout(function () {
formContext.data.entity.attributes.forEach(function (attr) {
if (attr.getIsDirty()) {
attr.setSubmitMode("never");
console.log("Dirty flag cleared for: " + attr.getName());
}
});
console.log("All dirty fields cleared from the form.");
}, 3000); // adjust delay as needed
}
This approach should still be used with some caution. The best practice is to first understand why certain fields are showing as dirty and, if possible, fix the underlying cause. The script should only be used in specific situations where we are confident that the dirty fields are not needed for saving the record. It’s also important to add the right checks or conditions so that it doesn’t run everywhere unnecessarily.
For example, in our case we only applied it when the form was in a particular status where it was expected to be read-only for the user. The fields were already hidden, so letting them stay dirty served no purpose.
Hope it helps..
