If you open Custom Page modals from many places in your Dynamics 365 app, you quickly notice a problem: the same JavaScript gets copied again and again, each button hard-codes its own page name and sizes, and one small change means editing a dozen web resources. The fix is a reusable PCF dialog framework — a single, well-designed layer that opens any Custom Page as a modal with consistent behavior.
This article — part of our series on hosting PCF controls in modal popups — shows you how to build that framework step by step, in plain language.
Why You Need a Framework
Without a shared layer, every dialog is a one-off. That leads to duplicated code, inconsistent dialog sizes, and no single place to add logging, error handling, or a loading state. A framework solves all of this by giving you one function to open any dialog and one place to change behavior.
- Consistency — every dialog looks and behaves the same.
- Less code — buttons just say “open this page with this record.”
- Easy maintenance — change sizing or error handling in one file.
- Reusability — new dialogs need almost no new code.
The Core Idea
The framework is a single helper (a JavaScript web resource) that wraps Xrm.Navigation.navigateTo(). Every ribbon button calls the helper with a small options object instead of writing its own navigation code.
// cloudverve_dialogFramework.js — one shared web resource
var CloudVerve = window.CloudVerve || {};
CloudVerve.Dialog = (function () {
function open(config, primaryControl) {
var ctx = primaryControl;
var recordId = config.recordId ||
(ctx && ctx.data.entity.getId().replace(/[{}]/g, ""));
var entityName = config.entityName ||
(ctx && ctx.data.entity.getEntityName());
var pageInput = {
pageType: "custom",
name: config.pageName, // logical name of the Custom Page
recordId: recordId,
entityName: entityName
};
var options = {
target: 2, // modal dialog
position: config.position || 1, // center by default
width: config.width || { value: 60, unit: "%" },
height: config.height || { value: 70, unit: "%" },
title: config.title || "Dialog"
};
return Xrm.Navigation.navigateTo(pageInput, options).then(
function () { if (config.onClose) config.onClose(ctx); },
function (e) { CloudVerve.Dialog._error(e); }
);
}
return {
open: open,
_error: function (e) { console.error("[CloudVerve.Dialog]", e); }
};
})();
Calling the Framework from a Button
Now any ribbon button is a one-liner. It describes what to open, not how:
function openCustomer360(primaryControl) {
CloudVerve.Dialog.open({
pageName: "cr123_customer360_page",
title: "Customer 360",
width: { value: 70, unit: "%" },
height: { value: 80, unit: "%" },
onClose: function (ctx) { ctx.data.refresh(false); }
}, primaryControl);
}
Every dialog in your app now flows through the same code path — so sizing, titles, error handling, and the post-close refresh are all consistent.
Adding Shared Features
Because everything runs through one function, you can add powerful features in a single place and every dialog gets them for free:
- Standard sizes — small, medium, large presets instead of magic numbers.
- Loading indicators — show a spinner while the page loads.
- Central error handling — one place to log and show friendly messages.
- Telemetry — track which dialogs are used and how often.
- Auto-refresh — refresh the parent form or a named subgrid on close.
Best Practices
- Keep the framework in one web resource and version it carefully.
- Use named size presets so dialogs stay visually consistent.
- Always pass only the data the page needs.
- Handle the no-record case (dialogs opened from a grid or the nav bar).
- Document the
configoptions so any developer can add a dialog.
Conclusion
A reusable PCF dialog framework turns dozens of copy-pasted scripts into a single, reliable helper. You write less code, ship consistent dialogs, and gain one place to improve every popup at once. It’s the foundation that makes the rest of this series — passing data, AI panels, multi-dialog flows, and wizards — simple to build.
Related: start with the cornerstone guide, How to Open a PCF Control in a Modal Popup Using Custom Pages in Dynamics 365.
Want a production-ready dialog framework for your model-driven apps? Talk to the CloudVerve team.