You want a button on a record's form — "Quick Actions," "Send for Approval," whatever the scenario — that pops open a purpose-built screen instead of just editing a field. That screen is a Custom Page, and getting a button to open one takes two small pieces: the page itself, and a command wired to open it. This post covers both, plus the JavaScript version when you need real control over how it opens.

Quick facts

Custom Page vs. Power Pages — don't mix these up

Same word, different products. A Custom Page is a canvas-app-style screen that lives inside a model-driven app, for your internal users. Power Pages (covered in its own course on this site) is a full external-facing website for people outside your organization. This post is about the former — a screen your own team sees, opened from a button on a form.

Step 1 — Build the custom page

  1. In the model-driven app's designer, go to PagesNew pageCustom page.
  2. Design it like any canvas app — controls, data sources, formulas.
  3. Save and publish it.
  4. Note its unique name (visible in the page's properties, something like cr123_mycustompage_e6a2b) — the button needs this exact value.
Example A "Log a Quick Note" custom page with a single text input and a submit button, opened from a Contact form so a support rep can jot something down without opening the full form's Notes section.

Step 2a — The low-code way (modern command bar)

If you don't need to pass data or control the dialog size, this is the fastest path:

  1. Open the form (or table) in the app designer, go to the Command bar designer.
  2. Add a new button, set its label and icon.
  3. Set its action to a Power Fx formula: Navigate(YourCustomPageName)
  4. Save and publish.

That's genuinely it for the simple case — no code, no ribbon XML.

Step 2b — The JavaScript way (when you need control)

For control over dialog size, position, or passing the current record's ID into the page, add a command with a Run JavaScript action instead, pointing at a function like this:

function openQuickNotePage(primaryControl) {
    var pageInput = {
        pageType: "custom",
        name: "cr123_mycustompage_e6a2b",
        entityName: primaryControl.data.entity.getEntityName(),
        recordId: primaryControl.data.entity.getId()
    };

    var navigationOptions = {
        target: 2,
        width: { value: 60, unit: "%" },
        height: { value: 70, unit: "%" },
        position: 1
    };

    Xrm.Navigation.navigateTo(pageInput, navigationOptions).then(
        function success() {
            // page was closed
        },
        function error(err) {
            console.log("Could not open custom page: " + err.message);
        }
    );
}

Two things worth calling out in that code:

A note on the unique name

The name value has to match the custom page's unique name exactly. If the page gets renamed or recreated, that name can change — if the button suddenly stops opening anything, this is the first thing to check.

Key takeaway: A Custom Page opens inside a model-driven app for your own users — don't confuse it with Power Pages, which is external-facing. The Power Fx Navigate() action covers the simple case with zero code; reach for Xrm.Navigation.navigateTo() when you need to control the dialog's size or pass the current record into the page.