Navigating to a custom page using client API

This article provides examples of navigating from a model-driven app page to a custom page using Client API.

This article outlines the steps to use client API to open a custom page as a full-page, dialog, or pane. It provides examples of custom as a pageType value in navigateTo (Client API reference).

Important

Custom pages are a new feature with significant product changes and currently have a number of known limitations outlined in Custom Page Known Issues.

Finding the logical name

Each of the following client API examples takes the logical name of the custom page as the required parameter. The logical name is the Name value of the page in the solution explorer.

Find page logical name.

Open as an inline full page without context

Within a model-driven app client API event handler, call the following code and update the name parameter to be the logical name of the page.

// Inline Page
var pageInput = {
    pageType: "custom",
    name: "<logical name of the custom page>",
};
var navigationOptions = {
    target: 1
};
Xrm.Navigation.navigateTo(pageInput, navigationOptions)
    .then(
        function () {
            // Called when page opens
        }
    ).catch(
        function (error) {
            // Handle error
        }
    );

Open as an inline full page with a record context

This example uses the recordId parameter within the NavigateTo function to provide the custom page with the record to use.

// Inline Page
var pageInput = {
    pageType: "custom",
    name: "<logical name of the custom page>",
    entityName: "<logical name of the table>",
    recordId: "<record id>",
};
var navigationOptions = {
    target: 1
};
Xrm.Navigation.navigateTo(pageInput, navigationOptions)
    .then(
        function () {
            // Called when page opens
        }
    ).catch(
        function (error) {
            // Handle error
        }
    );

The Param function within the custom page retrieves the value and uses the Lookup function to retrieve the record.

App.OnStart=Set(RecordItem, 
    If(IsBlank(Param("recordId")),
        First(<entity>),
        LookUp(<entity>, <entityIdField> = GUID(Param("recordId"))))
    )

Important

The recordId parameter must be a GUID because it updates the URL and an app start from the URL will validate the recordId is a GUID.

Open as a centered dialog

Within a model-driven app client API event handler, call the following code and update the name parameter to be the logical name of the custom page. This mode supports the sizing parameters similar to the Main form dialogs.

// Centered Dialog
var pageInput = {
    pageType: "custom",
    name: "<logical custom page name>",
};
var navigationOptions = {
    target: 2, 
    position: 1,
    width: {value: 50, unit:"%"},
    title: "<dialog title>"
};
Xrm.Navigation.navigateTo(pageInput, navigationOptions)
    .then(
        function () {
            // Called when the dialog closes
        }
    ).catch(
        function (error) {
            // Handle error
        }
    );

Open as a side dialog

Within a model-driven app client API event handler, call the following code and update the name parameter to be the logical name of the custom page.

// Side Dialog
var pageInput = {
    pageType: "custom",
    name: "<logical page name>",
};
var navigationOptions = {
    target: 2, 
    position: 2,
    width: {value: 500, unit: "px"},
    title: "<dialog title>"
};
Xrm.Navigation.navigateTo(pageInput, navigationOptions)
    .then(
        function () {
            // Called when the dialog closes
        }
    ).catch(
        function (error) {
            // Handle error
        }
    );

This example uses the recordId parameter within the navigateTo function to provide the custom page with the record to use. The Param function within the custom page retrieves the value and uses the Lookup function to retrieve the record.

A more complete example of this can be found at Override the default open behavior of data rows in an entity-bound grid.

  1. Create a web resource of type JScript and update the name parameter to be the logical page name. Add the following code to the web resource.

    function run(selectedItems)
    {
        let selectedItem = selectedItems[0];
    
        if (selectedItem) {     
            let pageInput = {
                pageType: "custom",
                name: "<logical page name>",
                entityName: selectedItem.TypeName,
                recordId: selectedItem.Id,
            };
            let navigationOptions = {
                target: 1
            };
            Xrm.Navigation.navigateTo(pageInput, navigationOptions)
                .then(
                    function () {
                        // Handle success
                    }
                ).catch(
                    function (error) {
                        // Handle error
                    }
                );
        }
    }
    
  2. Customize the table ribbon CommandDefinition for OpenRecordItem to call the function above and include the CrmParameter with the value SelectedControlSelectedItemReferences.

        <CommandDefinition Id="Mscrm.OpenRecordItem">
            <Actions>
                <JavaScriptFunction FunctionName="run" Library="$webresource:cr62c_OpenCustomPage">
                    <CrmParameter Value="SelectedControlSelectedItemReferences" />
                </JavaScriptFunction>
            </Actions>
        </CommandDefinition>
    
  3. In the custom page, override the App's OnStart property to use the Param function to get the recordId and lookup record.

    App.OnStart=Set(RecordItem, 
        If(IsBlank(Param("recordId")),
            First(<entity>),
            LookUp(<entity>, <entityIdField> = GUID(Param("recordId"))))
        )
    

    Note

    After changing the OnStart property, you'll need to run OnStart from the App context menu. This function performs only once within a session.

  4. Then, the custom page can use the RecordItem parameter as a record. Below is an example on how to use it in an EditForm.

    EditForm.Datasource=<datasource name>
    EditForm.Item=RecordItem
    

Open from a selected record in editable grid as a centered dialog with record ID

Editable grid can be used to trigger OnRecordSelect event for scenarios where you want to perform an action when a particular record is selected in a view. This example uses the recordId parameter within the navigateTo function to provide the custom page with the record to use. The record ID is retrieved using the getId method in GridEntity object. The Param function within the custom page retrieves the value and uses the lookup function to retrieve the record.

  1. Enable editable grid control in the table.

  2. Create a web resource of type JScript and update the name parameter to be the logical page name. Add the following code to the web resource.

    function RunOnSelected(executionContext) {
    // Retrieves the record selected in the editable grid
    var selectedRecord = executionContext.getFormContext().data.entity;
    var Id = selectedRecord.getId().replace(/[{}]/g, ""); 
    
    // Centered Dialog
    var pageInput = {
        pageType: "custom",
        name: "<logical page name>",
        recordId: Id,
    };
    var navigationOptions = {
        target: 2,
        position: 1,
        width: { value: 50, unit: "%" },
        title: "<dialog title>"
    };
    Xrm.Navigation.navigateTo(pageInput, navigationOptions)
        .then(
            function () {
                // Called when the dialog closes
            }
        ).catch(
            function (error) {
                // Handle error
            }
        );
     }
    
  3. In the custom page, override the App's OnStart property to use the Param function to get the recordId and lookup record.

    App.OnStart=Set(RecordItem, 
        If(IsBlank(Param("recordId")),
            First(<entity>),
            LookUp(<entity>, <entityIdField> = GUID(Param("recordId"))))
        )
    

    Note

    After changing the OnStart property, you'll need to run OnStart from the App context menu. This function performs only once within a session.

  4. Then, the custom page can use the RecordItem parameter as a record. Below is how to use it in an EditForm.

    EditForm.Datasource=<datasource name>
    EditForm.Item=RecordItem
    

Model-driven app custom page overview
Add a custom page to your model-driven app
navigateTo (client API reference)