You open a Custom Page modal, the user edits data, the dialog closes — and the form behind it still shows the old values. Frustrating, and a common complaint. The fix is knowing exactly how to refresh a model-driven form after closing a Custom Page so the UI always reflects what just changed.
This guide — part of our series on hosting PCF controls in modal popups — covers every refresh you might need, in plain language.
Why the Form Doesn’t Refresh Automatically
A Custom Page runs in its own context. When it writes to Dataverse and closes, the model-driven form has no idea anything changed — it’s still showing data it loaded earlier. You have to tell it to reload.
The Key: the navigateTo Success Callback
Xrm.Navigation.navigateTo() returns a promise that resolves when the dialog closes. That callback is where you refresh:
function openAndRefresh(primaryControl) {
const formContext = primaryControl;
Xrm.Navigation.navigateTo(
{ pageType: "custom", name: "cr123_editor_page",
recordId: formContext.data.entity.getId().replace(/[{}]/g, ""),
entityName: formContext.data.entity.getEntityName() },
{ target: 2, width: { value: 60, unit: "%" } }
).then(function () {
// runs after the dialog closes
formContext.data.refresh(false); // reload the form
});
}
Refreshing Specific Parts
Sometimes reloading the whole form is overkill. You can refresh just what changed:
- Whole form:
formContext.data.refresh(false)(false= don’t prompt to save). - A subgrid:
formContext.getControl("SubgridName").refresh(). - A timeline: refresh it like a subgrid using its control name.
- Ribbon/command bar:
formContext.ui.refreshRibbon()to re-evaluate button rules. - A single field’s data: reload the attribute or refresh the form section.
Only Refresh When Something Changed
If the user cancels, there’s no need to reload. Have the Custom Page return a result (see Pass Data Between Custom Pages and PCF Controls), and refresh only when the result says data was saved:
.then(function (result) {
if (result && result.saved) {
formContext.data.refresh(false);
}
});
Common Pitfalls
- Refreshing too early: do it in the
.then(), after the dialog closes. - Wrong control name: subgrid/timeline names are case-sensitive and must match the form.
- Unwanted save prompt: pass
falsetorefreshto skip the save dialog. - Stale ribbon: call
refreshRibbon()if button visibility depends on the change.
Conclusion
Refreshing a model-driven form after a Custom Page closes is all about the navigateTo success callback — and choosing the right scope: whole form, subgrid, timeline, or ribbon. Refresh only when data actually changed, and your users always see current data without a manual reload.
Related: Open a PCF Control in a Modal Popup Using Custom Pages. Need polished form interactions? Talk to the CloudVerve team.