Navigation to Custom Pages
Complete the full lesson to earn 25 points
Work through each section, then tap “Mark as Complete” on the last one.
✦ Skip the page breaks and see fewer ads — read each lesson on a single page with Pro
Module: Extend the User Experience
Section: Apply Business Logic in Model-Driven Apps
Lesson: Navigation to Custom Pages
Introduction: Bridging the Gap in Model-Driven Apps
Model-driven apps are powerful tools for managing complex business data, but they often face limitations when it comes to highly specialized user interfaces. When you rely solely on standard forms, views, and dashboards, you may find yourself struggling to implement unique layouts or interactive experiences that don't fit the rigid structure of the Dataverse platform. This is where Custom Pages come into play. A Custom Page is essentially a canvas app integrated into a model-driven app, allowing you to design a fully bespoke interface while still operating within the context of your data-driven solution.
Navigating to these pages is not just about moving from one screen to another; it is about creating a fluid, professional experience for the end user. If navigation feels disjointed or confusing, users will struggle to adopt the application, regardless of how functional the backend logic might be. Mastering the navigation patterns between model-driven forms and custom pages allows you to orchestrate a sophisticated workflow that feels like a single, unified system. In this lesson, we will explore the mechanics, methods, and strategic considerations for implementing effective navigation in your custom-extended applications.
Understanding the Navigation Context
Before we dive into the code and configuration, it is essential to understand that a Custom Page in a model-driven app behaves differently than a standalone canvas app. When you navigate to a Custom Page, you are not just opening a new screen; you are often passing data context, maintaining state, and ensuring that the user can return to their previous location without losing their place.
There are two primary ways to initiate navigation: through the App Designer's site map or through programmatic commands using the Power Apps Client API. Understanding when to use which is the first step in building a predictable user experience. The site map is your go-to for static, high-level navigation, while the Client API provides the dynamic, context-aware navigation required for complex business processes.
Callout: Custom Pages vs. Standalone Canvas Apps While both use the Power Apps Studio interface, a Custom Page is specifically designed to host inside the model-driven app shell. This means it inherits the model-driven app's theme, navigation bar, and command bar. A standalone canvas app, by contrast, acts as a separate entity that often requires its own authentication flow and design language, making it feel detached from the rest of your business data environment.
Method 1: Declarative Navigation via Site Map
The site map is the backbone of your model-driven app's navigation. Adding a Custom Page here is the simplest way to make it accessible to users. This approach is best for pages that act as landing zones, specialized dashboards, or utility screens that do not require specific data context to initialize.
Step-by-Step: Adding to the Site Map
- Open the App Designer: Navigate to your solution and open your model-driven app in the editor.
- Add a New Page: Within the Pages pane, click on "+ New Page."
- Select Custom Page: Choose the "Custom" option. You can either select an existing page from your solution or create a new one from scratch.
- Configure Navigation: Once added, the page will appear in your left-hand navigation menu. You can drag and drop it into specific groups or sub-areas to categorize it logically.
- Publish: Always remember to save and publish your app changes. The navigation update will not be visible to end users until the app metadata is refreshed.
Tip: Organize for Clarity Avoid cluttering the site map with too many custom pages. If you have several specialized pages, group them under a single sub-area named "Tools" or "Dashboards" to keep the main navigation menu clean and intuitive for the user.
Method 2: Programmatic Navigation with the Client API
For most business scenarios, you need to navigate to a Custom Page based on a user action—such as clicking a button on a form or triggering a workflow. This is where the navigateTo function within the Xrm.Navigation namespace becomes indispensable. This method allows you to pass parameters, define the display mode (side panel vs. full page), and ensure the user stays within the context of the record they are viewing.
The Syntax of navigateTo
The Xrm.Navigation.navigateTo function is a powerful tool that accepts an object containing the page information and navigation options. Here is the basic structure:
var pageInput = {
pageType: "custom",
name: "new_custompage_unique_name"
};
var navigationOptions = {
target: 2, // 1 for full page, 2 for side panel
position: 2, // 1 for centered, 2 for side
width: { value: 40, unit: "%" } // Percentage or pixels
};
Xrm.Navigation.navigateTo(pageInput, navigationOptions).then(
function success() {
console.log("Navigation successful");
},
function error(err) {
console.log("Navigation failed: " + err.message);
}
);
Breaking Down the Parameters
- pageType: Must be set to "custom" for Custom Pages.
- name: This is the logical name of your custom page, not the display name. You can find this in the solution explorer.
- target: This dictates how the page opens. Using
2for a side panel is often preferred for data entry or quick lookups because it allows the user to see the underlying record, providing a sense of continuity. - position: Defines whether the side panel appears on the right or left.
- width: Allows you to control the screen real estate. Using percentages is generally better for responsiveness across different screen sizes.
Handling Data Context and Parameters
One of the most common requirements in business applications is passing information from the current record to the custom page. For example, if a user is on an "Account" form and clicks a button to "Generate Custom Report," you need to pass the Account ID to the custom page so it knows which data to fetch.
Passing Parameters
You can add a data property to the pageInput object. This property accepts a JSON object, which can then be parsed within the Custom Page using the Param() function in Power Fx.
JavaScript (The Caller):
var pageInput = {
pageType: "custom",
name: "new_reportpage_name",
data: JSON.stringify({ accountId: formContext.data.entity.getId() })
};
Power Fx (Inside the Custom Page):
// Use the Param function to retrieve the data
Set(varAccountId, JSON(Param("data")).accountId);
Warning: Data Security While passing parameters via
datais convenient, never pass sensitive information like passwords or PII (Personally Identifiable Information) that is not meant for the client side. Ensure that the logic inside your custom page validates the incoming ID to prevent unauthorized data access if the user attempts to manipulate the URL.
Best Practices for Navigation Design
Designing navigation is as much about user psychology as it is about technical implementation. If your navigation is unpredictable, users will feel like they are "trapped" in the application. Follow these best practices to ensure a smooth experience.
1. Consistent Exit Points
Always provide a clear way to close the custom page. If you are using a side panel, the system provides a close button, but if you are using a full-page view, you should include a "Back" or "Cancel" button that uses the back() method of the navigation API to return the user to the previous screen.
2. Use Side Panels for Quick Tasks
Side panels are excellent for quick, non-disruptive tasks. If a task requires the user to focus on a complex form, a full-page navigation is better. Match the "weight" of the navigation container to the complexity of the task.
3. Loading States
Custom pages often load data asynchronously. Implement a clear loading state (a spinner or a simple "Loading..." label) within your custom page so the user doesn't think the application has frozen.
4. Responsive Design
Model-driven apps are used on everything from ultra-wide monitors to tablets. When you configure the width in your navigation options, test it on multiple screen sizes. A side panel that takes up 80% of the screen on a laptop might be unusable on a smaller tablet.
Comparison: Navigation Options
| Feature | Site Map Navigation | Programmatic (Client API) |
|---|---|---|
| Trigger | User clicks menu item | Button click / Event-based |
| Flexibility | Static | Highly dynamic |
| Context | Global / App-wide | Record-specific / Local |
| Targeting | Always full screen | Panel or full screen |
| Complexity | Low (No code) | Medium (Requires JavaScript) |
Common Pitfalls and Troubleshooting
Even with a solid plan, developers often encounter issues when implementing navigation. Here are the most common mistakes and how to resolve them.
Pitfall 1: Hardcoding IDs
Never hardcode IDs in your navigation logic. Always use the formContext to retrieve the current record's ID. Hardcoding creates brittle code that will fail when moved to a different environment (like from Development to Production) where the GUIDs for records will differ.
Pitfall 2: Forgetting to Publish
This sounds trivial, but it is the number one reason for "it's not working" support tickets. When you modify the site map or update the custom page configuration, the changes are local to your session until you publish the app. If you don't see your changes, check the version history and publication status.
Pitfall 3: Not Handling Empty Data
If your custom page relies on an incoming parameter, what happens if that parameter is missing? Your Power Fx logic should always include a check to see if the parameter is null or empty. If it is, redirect the user back to the home page or display a friendly error message instead of letting the page crash.
// Best practice for null checking
If(IsBlank(Param("data")),
Notify("Missing record context", NotificationType.Error); Back(),
// Proceed with normal logic
)
Pitfall 4: Over-complicating the Side Panel
The side panel is a constrained space. Do not attempt to build a complex, multi-tabbed, multi-level navigation system inside a side panel. If your custom page needs its own internal navigation, it should probably be a full-page experience.
Advanced Scenario: Navigating Back with Data
Sometimes, you need to return information from the custom page to the model-driven form. While the navigateTo API is primarily for opening pages, you can manage state by saving the data back to the Dataverse record before calling Back().
- Perform the work: The user interacts with the custom page and clicks "Save."
- Patch the data: Use the
Patch()function in Power Fx to update the record in Dataverse. - Return to form: Use the
Back()function to return to the model-driven form. - Refresh the form: Since the model-driven form might still be open in the background, you can use the
OnVisibleproperty or a timer to refresh the form data once the user returns, ensuring they see the changes immediately.
Callout: The Power of
Back()TheBack()function is not just a browser-style "go back." It is a managed navigation command that respects the history stack of the model-driven app. Using this ensures that the user's breadcrumbs and navigation history remain intact, which is critical for an enterprise-grade user experience.
Industry Recommendations for Large-Scale Apps
If you are building a large, multi-departmental application, navigation can become a management nightmare. Here are some industry-standard strategies to keep your app performant and maintainable.
Use a "Command Center" Pattern
Instead of having 20 different custom pages in your site map, have one "Command Center" custom page that acts as a router. The user navigates to the Command Center, which then uses a gallery or a menu to navigate to other sub-pages. This keeps your site map clean and allows you to centralize your navigation logic.
Standardize Your Page Names
Establish a naming convention for your custom pages early in the project. For example: Page_Department_TaskName. This makes it much easier to find the correct page when you are writing the Xrm.Navigation code.
Implement Logging for Navigation
If you have a complex app, add a simple logging function to your navigation calls. You can write the navigation events to a custom Dataverse table. This is invaluable when users report issues, as you can see exactly which page they were trying to navigate to and what parameters were passed.
Frequently Asked Questions
Q: Can I open a model-driven form from a Custom Page?
A: Yes. You can use the Navigate() function in Power Fx to open a model-driven record form. This is the standard way to "drill down" from a custom dashboard into a specific record.
Q: Does navigation to a Custom Page trigger the OnStart property?
A: Yes, the App.OnStart property runs when the custom page is loaded. Keep your OnStart logic lean to ensure the page loads quickly.
Q: Can I pass complex objects via data?
A: The data parameter is a string. You should always use JSON.stringify to pass data and JSON() or ParseJSON() to read it. Keep the object as small as possible to avoid URL character limits.
Q: What happens if the user refreshes the browser while on a Custom Page? A: The page will reload, and the parameters passed to it will be preserved in the URL. Ensure your page is designed to handle this by reading parameters on load rather than just on initialization.
Summary of Key Takeaways
- Context is King: Always consider the user's current context (the record they are viewing) when deciding how to navigate. Passing the record ID allows for a cohesive experience.
- Choose the Right Container: Use the site map for high-level, static pages and the Client API for dynamic, context-aware navigation.
- Prioritize User Experience: Use side panels for quick actions to keep the user in the flow of their work, and reserve full-page navigation for complex tasks that require full attention.
- Validation is Essential: Always validate parameters passed to your custom page. Never assume that the data will be present or in the expected format.
- Maintainability Matters: Use consistent naming conventions and avoid hardcoding values. A well-structured navigation system is much easier to debug and scale.
- The
Back()Function: Always use the built-in navigation functions (Back(),Navigate()) rather than trying to force browser-based navigation, as this preserves the integrity of the model-driven app state. - Testing is Non-Negotiable: Because custom pages can behave differently based on the device, always test your navigation logic on multiple screen sizes and browsers before moving to production.
By following these principles, you move beyond simply "building pages" and start "designing workflows." A well-navigated application is one where the user never has to guess where they are or how to get back to where they started. This level of polish is what separates a functional tool from a professional-grade business solution. As you continue to build out your model-driven applications, keep these patterns in mind, and you will find that the integration between custom interfaces and standard data forms becomes a powerful asset in your development toolkit.
Continue the course
Enjoying the courses?
Everything stays free. Pro shows fewer ads, doubles your daily points limit so you progress twice as fast, and lets you read each lesson on one page.
- ✓ Fewer advertisements
- ✓ 2× daily points limit
- ✓ Distraction-free lessons