Configuring Custom Pages

Earn 25 points (50 with Pro) in two steps

  1. ① Read through the lesson — each section gets a ✓ as you scroll through it.
  2. ② When every section has a ✓, tap Complete lesson.

0 of 12 read · keep scrolling

✦ See fewer ads and earn double points — 50 a lesson instead of 25 — with Pro

Configuring Custom Pages in Model-Driven Apps

Welcome to this in-depth lesson on configuring custom pages within Microsoft Power Apps model-driven applications. As you build more sophisticated business solutions, you'll often encounter scenarios where the standard forms, views, and dashboards of a model-driven app don't quite meet the unique user experience or complex functional requirements. This is precisely where custom pages come into play, offering a powerful bridge between the structured world of model-driven apps and the highly flexible, pixel-perfect design capabilities of canvas apps.

This lesson will guide you through understanding, creating, and implementing custom pages, demonstrating how they can significantly enhance the user interface and functionality of your model-driven applications. We'll cover everything from the fundamental concepts to advanced communication patterns, best practices, and common pitfalls, ensuring you have the knowledge to leverage this feature effectively.

Not read yet

1. Introduction: Bridging the Gap with Custom Pages

Model-driven apps are fantastic for rapidly building business applications based on Dataverse data, providing a consistent user experience with forms, views, and dashboards. They excel at data management and process enforcement. However, their strength lies in standardization, which can sometimes be a limitation when you need a highly tailored user interface, intricate data visualizations, or a multi-source data experience that doesn't fit neatly into a record-centric form.

Enter Custom Pages. A custom page is essentially a canvas app embedded within a model-driven app. This means you can design a screen with the full flexibility of the canvas app designer – using custom layouts, rich controls, complex Power Fx logic, and connecting to a wide array of data sources – and then seamlessly integrate it into your model-driven app's navigation, forms, or dialogs. It empowers app makers to deliver bespoke user experiences without completely abandoning the benefits of a model-driven architecture.

Why Custom Pages Matter:

  • Enhanced User Experience (UX): Deliver highly customized, intuitive interfaces that go beyond standard model-driven forms. Imagine complex dashboards, guided processes, or unique data entry screens.
  • Complex UI/UX Requirements: When standard forms are too restrictive for intricate layouts, multi-step wizards, or dynamic content presentation.
  • Canvas App Flexibility within Model-Driven Apps: Leverage the rich control set, advanced Power Fx formulas, and diverse data connectors of canvas apps.
  • Multi-Source Data Integration: Display data from Dataverse alongside data from SQL Server, SharePoint, Excel, or custom APIs all on one screen.
  • Reduced Development Time: Instead of building custom HTML/JavaScript web resources for complex UI, you can often achieve the desired result faster with Power Fx and canvas app controls.
  • Consistency: While offering flexibility, custom pages still inherit some theming from the model-driven app, helping maintain a cohesive look and feel.

In essence, custom pages allow you to pick the best features from both Power Apps worlds, providing a powerful tool for creating truly comprehensive and user-friendly business applications.

Not read yet

2. Understanding the Need for Custom Pages

Before diving into creation, let's solidify why you would choose a custom page over existing model-driven components. Model-driven apps provide a wealth of functionality out-of-the-box, but they are inherently designed around records and data forms.

Limitations of Standard Model-Driven Components:

  • Fixed Layouts: Forms and views have predefined section and tab layouts. While configurable, they lack the pixel-perfect control of a canvas app.
  • Limited Control Set: The controls available on model-driven forms are primarily for data entry and display related to a single record. Complex charting, interactive maps, or highly custom UI elements are not native.
  • Single Data Source Focus (Dataverse): While you can embed subgrids and related records, bringing in truly disparate data sources (e.g., a SQL database, a third-party API, and Dataverse) onto a single, cohesive screen is challenging without custom development.
  • Complex Business Logic: While business rules and process flows are powerful, highly interactive, client-side logic that involves dynamic UI changes based on user input across multiple data points is often simpler to implement in Power Fx.
  • Branding and Theming: While theming can be applied to model-driven apps, the degree of visual customization for specific screens is limited compared to canvas apps.

Scenarios Where Custom Pages Shine:

Consider these practical examples where custom pages provide superior solutions:

  • Guided Onboarding Wizards: A multi-step process for new employees or customers, collecting data across several Dataverse tables and presenting progress visually.
  • Executive Dashboards: A custom-designed dashboard pulling aggregated data from Dataverse, an external financial system, and a marketing analytics platform, all presented with interactive charts and KPIs.
  • Complex Order Entry Screens: An interface allowing users to select products, configure options, view real-time inventory from an external system, and calculate complex pricing, all before creating an order record in Dataverse.
  • Custom Search and Filtering: A highly visual search interface for products or services that allows users to apply multiple filters, view results in a custom gallery, and then navigate to a Dataverse record.
  • Interactive Maps: Displaying Dataverse records (e.g., customer locations, service areas) on an interactive map, allowing users to select points and view related details in context.
  • Calculators or Quoting Tools: A dedicated screen where users input various parameters, and the app performs complex calculations, displaying instant results and potentially generating a quote record.

Callout: The Power of Context Custom pages aren't just standalone canvas apps; they are context-aware. When embedded in a model-driven app, they can receive information from the host app, such as the current record's ID, the user's context, or other parameters. This seamless communication is what makes them so powerful for extending the model-driven experience, rather than just linking to a separate app.

Not read yet

3. Anatomy of a Custom Page

A custom page, at its core, is a specialized type of canvas app. However, it operates within the confines and context of a model-driven app, leading to some unique characteristics.

Key Characteristics:

  • It's a Canvas App: All your knowledge of canvas app design, controls, and Power Fx applies directly to custom pages. You design them using the same Power Apps Studio.
  • It Lives within a Solution: Custom pages must be created and managed within a Power Apps solution. This is crucial for application lifecycle management (ALM) and deployment.
  • Host Object for Communication: This is the most critical distinction. A custom page has access to a Host object, which facilitates interaction with the parent model-driven app. This object allows you to:
    • Retrieve parameters passed from the model-driven app (Host.Param).
    • Navigate within the model-driven app (Host.NavigateTo).
    • Close the custom page (Host.Back).
    • Refresh the host form/view (Host.RefreshHost).
  • No Standalone Play: Custom pages cannot be played directly as standalone canvas apps. They are designed exclusively to function within a model-driven app.
  • Inherited Theming: Custom pages often pick up some of the theming from the model-driven app, helping them blend in visually.

Understanding the Host Object

The Host object is your gateway to interacting with the model-driven app context. Let's look at its key properties and methods:

  • Host.Param("ParameterName"): Retrieves a specific parameter passed to the custom page from the model-driven app. For example, if you open a custom page from a form and pass the current record's GUID as recordId, you'd access it using Host.Param("recordId").
  • Host.Back(OptionalDataToReturn): Closes the custom page. If the page was opened as a dialog, OptionalDataToReturn can be used to pass data back to the calling model-driven component.
  • Host.RefreshHost(): Refreshes the underlying model-driven form or view that opened the custom page. This is incredibly useful after a user performs an action in the custom page that updates data displayed on the host form.
  • Host.NavigateTo(Target, Parameters, Transition): Allows you to navigate to another page, form, view, or even another custom page within the same model-driven app.
    • Target: The name of the sitemap area, table, or custom page to navigate to.
    • Parameters: A record of parameters to pass to the target.
    • Transition: Visual transition (e.g., Transition.None, Transition.Cover).
  • Host.Context: Provides information about the model-driven app context, such as the current app ID, current user, etc. (Less commonly used than Host.Param or Host.NavigateTo).

Not read yet

4. Creating Your First Custom Page (Step-by-Step)

Let's walk through the process of creating a simple custom page and integrating it into a model-driven app. For this example, we'll create a custom page that allows a user to quickly update a specific field on an Account record and then return to the Account form.

Prerequisites:

  • Access to a Power Apps environment.
  • A model-driven app to integrate the custom page into (or create a new one).
  • A Dataverse table (e.g., Account table) with some sample data.

Step 1: Create a New Solution

It's a best practice to always work within solutions for ALM purposes.

  1. Navigate to make.powerapps.com.
  2. Select your environment from the top right.
  3. In the left navigation pane, click Solutions.
  4. Click New solution.
  5. Provide a Display name (e.g., "Custom Page Demo Solution").
  6. Choose a Publisher (create a new one if you don't have a suitable one).
  7. Click Create.

Step 2: Add a New Custom Page to the Solution

Now, let's create the custom page itself.

  1. Open your newly created solution.
  2. Click New > Page > Custom page (preview).
  3. Give your custom page a Name (e.g., "AccountQuickUpdatePage").
  4. Click Create.

This will launch the Power Apps Studio with a blank canvas app, specifically configured as a custom page. Notice the default screen size and the Host object available.

Step 3: Design the Custom Page

For our example, we want to display the account name and allow updating a "Description" field.

  1. Change Screen Size (Optional but Recommended): Custom pages often function better with a flexible width.

    • Select the screen in the tree view.
    • In the Properties pane on the right, under "Size," select a template like "Tablet" or "Phone" if you want a fixed size, or use custom dimensions. For a dialog, a smaller, fixed size is often appropriate. Let's set Width to 700 and Height to 400 for a simple dialog.
  2. Add a Label for the Account Name:

    • Insert a Text label control.
    • Set its Text property to "Account Name: " & Host.Param("accountName"). (We'll pass accountName from the model-driven app later).
    • Adjust font size and position.
  3. Add a Text Input for Description:

    • Insert a Text input control.
    • Rename it to txtDescription.
    • Set its Mode property to Multiline.
    • Set its Default property to Host.Param("accountDescription"). (We'll pass accountDescription later).
    • Adjust its width and height to allow for more text.
  4. Add a Button to Save Changes:

    • Insert a Button control.
    • Set its Text property to "Save and Close".
    • Rename it to btnSave.
    • Set its OnSelect property to the following Power Fx:
    // Update the Account record in Dataverse
    Patch(
        Accounts,
        LookUp(Accounts, Account = GUID(Host.Param("accountId"))),
        {
            Description: txtDescription.Text
        }
    );
    // Refresh the host form to show the updated description
    Host.RefreshHost();
    // Close the custom page
    Host.Back();
    
    • Explanation:
      • Patch(Accounts, ...): This is the core function to update a Dataverse record. Accounts is the table we're targeting.
      • LookUp(Accounts, Account = GUID(Host.Param("accountId"))): This finds the specific Account record to update. Host.Param("accountId") will provide the GUID of the current account from the model-driven form. We use GUID() to convert the text parameter into a GUID type.
      • { Description: txtDescription.Text }: This specifies the field to update (Description) and its new value (from our txtDescription input).
      • Host.RefreshHost(): After saving, this tells the model-driven app to refresh the form that opened this custom page. This ensures the user sees the updated description immediately.
      • Host.Back(): This closes the custom page, returning the user to the previous screen in the model-driven app.
  5. Add a Button to Cancel:

    • Insert another Button control.
    • Set its Text property to "Cancel".
    • Rename it to btnCancel.
    • Set its OnSelect property to Host.Back();. This simply closes the page without saving.

Step 4: Integrate the Custom Page into a Model-Driven App

Now that our custom page is designed, we need to make it accessible within our model-driven app. We'll add it as a dialog launched from a button on the Account form.

  1. Add the Account Table to Your Solution:
    • In your solution, click Add existing > Table.
    • Select Account and click Next.
    • Choose Select objects and select the Main Form (or any form you want to add the button to).
    • Click Add.
  2. Add the Custom Page to the Model-Driven App:
    • In your solution, find your model-driven app (or create a new one).
    • Open the model-driven app in the App Designer.
    • Click Pages > Add page.
    • Select Custom page and choose "AccountQuickUpdatePage".
    • Click Add. (This adds it as a component, but we won't use it directly from the sitemap for this example).
  3. Add a Command Button to the Account Main Form:
    • In your solution, navigate to Tables > Account > Forms.

    • Open the "Main" form for the Account table.

    • At the top, click ... (More commands) > Edit command bar.

    • Select the Main form command bar and click Edit. This opens the modern command designer.

    • Click + New command.

    • Set Label to "Quick Update Description".

    • Set Icon to a suitable icon (e.g., Edit).

    • For Action, select Run Power Fx.

    • In the formula bar, enter the following Power Fx:

      // Open the custom page as a dialog, passing parameters
      Navigate(
          {
              PageName: "AccountQuickUpdatePage", // The name of your custom page
              PageType: "Custom",
              // Parameters to pass to the custom page
              Data: {
                  accountId: Self.Selected.Item.Account, // Current record's GUID
                  accountName: Self.Selected.Item.'Account Name', // Current record's Name
                  accountDescription: Self.Selected.Item.Description // Current record's Description
              }
          },
          NavigateTarget.Dialog // Open as a dialog
      )
      
    • Explanation:

      • Navigate(...): This function is used in the model-driven command bar to open different pages.
      • PageName: "AccountQuickUpdatePage": Specifies the custom page to open.
      • PageType: "Custom": Indicates it's a custom page.
      • Data: {...}: This is where you define the parameters to pass.
        • accountId: We're passing the GUID of the current record using Self.Selected.Item.Account.
        • accountName: The name of the account.
        • accountDescription: The current description.
        • Important: The names (accountId, accountName, accountDescription) must exactly match what you use in Host.Param() within the custom page.
      • NavigateTarget.Dialog: This opens the custom page as a modal dialog, which is ideal for quick update scenarios. You could also use NavigateTarget.NewWindow or NavigateTarget.CurrentTab if you wanted it to replace the current form.
    • Choose where to display the command (e.g., "Main form" or "Subgrid").

    • Click Save and Publish.

Step 5: Test Your Custom Page

  1. Open your model-driven app.
  2. Navigate to the Accounts table and open an existing account record.
  3. You should see your "Quick Update Description" button in the command bar.
  4. Click the button. Your custom page should open as a dialog, displaying the account name and its current description.
  5. Modify the description, then click "Save and Close."
  6. The dialog should close, and the Account form should refresh, showing your updated description.

This hands-on example demonstrates the fundamental flow: creating the custom page, designing its UI and logic (including Power Fx to interact with Dataverse and the host app), and then integrating it into your model-driven app's command bar to pass context and receive feedback.

Not read yet

5. Data Interaction and Communication

The ability for a custom page to communicate bidirectionally with its host model-driven app is what makes it so powerful. Let's delve deeper into parameter passing and data return mechanisms.

Passing Parameters to a Custom Page

When you open a custom page, you often need to provide it with context from the model-driven app. This is done by passing parameters.

  • From Sitemap: When adding a custom page to the sitemap, you can define parameters in the "Parameters" field. These are static key-value pairs.

  • From Command Bar (Power Fx Navigate): This is the most common and dynamic method. As shown in the example above, the Data property of the Navigate function is a record that holds your parameters.

    // Example from a command button on an Account form
    Navigate(
        {
            PageName: "MyCustomPage",
            PageType: "Custom",
            Data: {
                recordId: Self.Selected.Item.Account,  // Pass the current record's GUID
                recordType: "account",                  // Pass the entity logical name
                someSetting: "true"                     // Pass a custom setting
            }
        },
        NavigateTarget.Dialog
    )
    
  • From JavaScript Web Resource: If you're opening a custom page from JavaScript (e.g., from a form script), you use Xrm.Navigation.navigateTo with the pageType set to custom and pass parameters in the data property.

    // Example from a JavaScript web resource on a form
    var pageInput = {
        pageType: "custom",
        name: "MyCustomPage", // Logical name of the custom page
        data: {
            recordId: Xrm.Utility.getPageContext().input.entityId,
            recordType: Xrm.Utility.getPageContext().input.entityTypeName
        }
    };
    Xrm.Navigation.navigateTo(pageInput);
    

Retrieving Parameters in the Custom Page (Host.Param())

Inside your custom page, you access these passed parameters using Host.Param("ParameterName").

// On the custom page, to get the record ID
Set(varRecordId, GUID(Host.Param("recordId")));

// To display the record type
"Current Entity: " & Host.Param("recordType")

// To use a boolean setting
If(Host.Param("someSetting") = "true", Notify("Setting is true!"), Notify("Setting is false!"))

Note: Host.Param() always returns a text string. If you expect a GUID, number, or boolean, you'll need to use conversion functions like GUID(), Value(), or Boolean() respectively.

Returning Data from a Custom Page

While custom pages are primarily for input and interaction, you might need to signal back to the host app or pass a simple result.

  • Host.Back(OptionalDataToReturn):
    • This closes the custom page.
    • If the custom page was opened as a dialog, you can pass a record of data back to the calling model-driven component. The Navigate function in the command bar (or Xrm.Navigation.navigateTo in JS) can optionally have a callback function to process this returned data.
    • Example (Custom Page OnSelect of a "Select" button):
      Host.Back({SelectedValue: Gallery1.Selected.ID, Message: "Item selected successfully"});
      
    • Example (Model-Driven Command Bar Navigate with Callback):
      // This is a more advanced scenario and often involves JavaScript
      // For Power Fx command bar, `Navigate` doesn't directly support a callback for returned data in this way.
      // Instead, `Host.RefreshHost()` is the primary way to signal changes.
      // If you need to "return" data to Power Fx, consider writing the data to a temporary Dataverse record
      // or using Host.RefreshHost() to trigger a refresh that reads updated data.
      
  • Host.RefreshHost():
    • This is the most common and effective way to signal that data has changed and the host form/view should reflect those changes. It doesn't pass specific data back, but it triggers a refresh of the underlying model-driven component. This is often sufficient when the custom page is modifying data that the host form is already displaying.
  • Host.NavigateTo(Target, Parameters, Transition):
    • This allows you to close the custom page and then navigate the model-driven app to a completely different page, form, or view. This is useful for complex workflows where the custom page is a step, and the next step is a different part of the model-driven app.
    • Example: After completing a complex setup in the custom page, navigate to the related record's main form.
      Host.NavigateTo(
          {
              PageType: "entityrecord",
              EntityName: "account",
              EntityId: GUID(Host.Param("accountId"))
          },
          Transition.Cover
      );
      

Interacting with Dataverse within the Custom Page

Since a custom page is a canvas app, you connect to Dataverse (and other data sources) just like any other canvas app.

  1. Add Dataverse tables: In the Power Apps Studio for your custom page, go to Data > Add data > Dataverse. Select the tables you need (e.g., Accounts, Contacts, Opportunities).

  2. Perform CRUD operations:

    • Read: Use LookUp(), Filter(), Search(), Sort() with galleries and forms to display data.
    • Create: Use Patch() or SubmitForm() with an Edit form.
    • Update: Use Patch() or SubmitForm() with an Edit form.
    • Delete: Use Remove() or RemoveIf().
    // Example: Create a new contact from the custom page
    Patch(
        Contacts,
        Defaults(Contacts),
        {
            'First Name': txtFirstName.Text,
            'Last Name': txtLastName.Text,
            'Email': txtEmail.Text,
            'Company Name (Accounts)': LookUp(Accounts, Account = GUID(Host.Param("accountId"))) // Link to the host account
        }
    );
    Notify("Contact created successfully!");
    Host.RefreshHost();
    Host.Back();
    

Not read yet

6. Advanced Custom Page Scenarios

Custom pages offer a lot of room for advanced implementations.

Responsive Design

One of the biggest advantages of custom pages is the ability to create responsive layouts, which is challenging with standard model-driven forms.

  • Fluid Layouts: Instead of fixed widths, use formulas like Parent.Width and Parent.Height for control dimensions to make them scale with the screen.
  • Containers: Use horizontal and vertical containers (from the "Layout" tab in the Insert pane) to manage the flow and alignment of controls. These containers are crucial for building truly responsive interfaces.
  • App.Width and App.Height: Use these global properties to adjust layouts based on the overall screen size or orientation. For example, you might have different layouts for App.Width < 600 (phone portrait) vs. App.Width >= 600 (tablet/desktop).
  • Self.Width / Self.Height: Refer to the control's own width/height.
  • X and Y Properties: For positioning, instead of hardcoded numbers, use formulas like (Parent.Width - Self.Width) / 2 to center a control horizontally.

Integrating with JavaScript/TypeScript (Web Resources)

While Power Fx covers most logic, sometimes you need to interact with client-side model-driven app features not exposed via Host object, or leverage existing JavaScript libraries.

  • Calling JavaScript from Power Fx:
    • This is generally not directly supported in custom pages in the same way it is for canvas apps embedded in model-driven forms (using Parent.Xrm.Utility.getResource).
    • However, you can use Host.NavigateTo to open another model-driven page (like a form) and pass parameters. That form could have a JavaScript web resource that runs on load and responds to those parameters. This is an indirect method.
    • A more direct approach involves having a JavaScript web resource on the host model-driven form. The custom page then uses Host.RefreshHost() or Host.Back() to trigger an event on the host form, and the JavaScript on the host form can then react to that event.
  • Calling Power Fx from JavaScript:
    • This is not directly supported. JavaScript on the model-driven form cannot directly call functions within the custom page.
    • Again, the typical pattern is for the JavaScript to manipulate data in Dataverse, and the custom page (or the host form itself) then reacts to those data changes.

Callout: Power Fx vs. JavaScript for Custom Pages

Feature Power Fx in Custom Page JavaScript in Model-Driven App Host
Primary Use UI logic, data manipulation, canvas app features. Model-driven form/view manipulation, advanced client-side integration, complex validations.
Data Access Direct access to Dataverse and 100s of connectors. Direct access to Dataverse via Web API (Xrm.WebApi), limited connector access.
UI Control Full control over custom page UI elements. Limited control over standard model-driven forms, can inject custom HTML/JS web resources.
Communication Host object for MD-app interaction. Xrm object for MD-app interaction.
Complexity Generally faster for UI logic, lower learning curve. Higher learning curve, more powerful for deep MD-app customization.
Best For Custom UI, multi-source data, guided processes, complex visualizations. Form events, ribbon button actions, deep integration with MD-app APIs.

Choose Power Fx for most custom page logic. Reserve JavaScript for scenarios where you need to interact deeply with the model-driven app's object model (e.g., specific form controls, business process flows, external library integration) that Power Fx cannot directly address.

Using Custom Connectors

Custom pages can leverage custom connectors, just like any other canvas app. This allows you to integrate with virtually any RESTful API, bringing external data and services directly into your model-driven app experience.

  1. Create your Custom Connector: Define the API endpoints, authentication, and request/response structures.
  2. Add to Custom Page: In the Power Apps Studio for your custom page, add the custom connector as a data source.
  3. Use in Power Fx: Call the custom connector's actions and functions within your Power Fx formulas to send and receive data.

Security Considerations

  • Sharing the Custom Page: The custom page, being a canvas app, must be shared with the users who will access the model-driven app. If it's not shared, users will see an error message. Share it with "User" permissions.
  • Data Source Permissions: Ensure users have the necessary Dataverse security roles and permissions to access the underlying Dataverse tables and records used by the custom page. If the custom page connects to other data sources (e.g., SQL, SharePoint), users also need permissions to those sources.
  • Environment Variables: For connection references or values that change between environments (Dev, Test, Prod), use environment variables within your custom page.

Not read yet

7. Best Practices for Custom Pages

To ensure your custom pages are performant, maintainable, and provide a great user experience, follow these best practices.

Performance

  • Minimize Data Calls: Fetch only the data you need. Use Filter(), LookUp(), and Select() to reduce the amount of data transferred. Avoid making repeated, identical data calls.
  • Optimize Power Fx Formulas: Complex formulas can impact performance. Break them down, use With() for intermediate calculations, and avoid delegable warnings.
  • Lazy Loading: For complex pages with many controls or data sources, consider loading less critical data only when it's needed (e.g., on a tab selection, or when a user scrolls).
  • Avoid ClearCollect() on OnStart: ClearCollect() can be slow. Use Collect() or Clear() in conjunction with Collect() on specific events rather than OnStart if possible.
  • Componentization: If you have reusable elements, create canvas components. This reduces redundancy and makes your app more efficient.

User Experience (UX)

  • Consistency with Model-Driven App Theme: While custom pages offer flexibility, try to align with the model-driven app's overall look and feel (fonts, colors, spacing) to create a cohesive experience.
  • Clear Navigation: Ensure users understand how to navigate within the custom page and how to return to the model-driven app. Use clear button labels (e.g., "Save," "Cancel," "Next," "Back").
  • Accessibility: Design with accessibility in mind. Use appropriate control types, provide meaningful labels, and ensure keyboard navigation works.
  • Error Handling and User Feedback: Implement Notify() functions for success, warning, and error messages. Provide clear feedback when operations are in progress (e.g., using a loading spinner).
  • Responsive Design: Plan your layout for different screen sizes if users will access the model-driven app on various devices. Utilize containers and flexible sizing.

Maintainability

  • Work in Solutions: Always create and manage custom pages within solutions. This is non-negotiable for ALM.
  • Clear Naming Conventions: Use consistent and descriptive names for your controls, variables, and collections (e.g., lblAccountName, txtDescription, btnSave, varSelectedRecord, colItems).
  • Comments: Add comments to complex Power Fx formulas to explain their purpose.
  • Modular Design: Break down complex logic into smaller, manageable pieces (e.g., using named formulas, reusable components).
  • Environment Variables: For connection references, URLs, or other values that vary between environments, use environment variables. This simplifies deployment and configuration.

Not read yet

8. Common Pitfalls and How to Avoid Them

Even with the best intentions, developers can run into issues with custom pages. Awareness is key to avoiding these common pitfalls.

  • Incorrect Parameter Passing:
    • Mistake: Mismatched parameter names between the Navigate function in the command bar and Host.Param() in the custom page. Incorrect data types (e.g., passing a string when a GUID is expected without conversion).
    • Avoid: Double-check parameter names for exact matches (case-sensitive). Always use GUID(), Value(), Boolean() to convert Host.Param() outputs to the correct data type in the custom page.
  • Security Issues (Page Not Loading):
    • Mistake: Forgetting to share the custom page (canvas app) with the relevant users or security groups.
    • Avoid: After creating and saving the custom page, ensure it is shared with "User" permissions to everyone who needs access to the model-driven app. Also, verify Dataverse security roles for underlying data.
  • Performance Bottlenecks:
    • Mistake: Making too many non-delegable data calls, complex formulas in OnStart, or fetching large datasets unnecessarily.
    • Avoid: Follow performance best practices (minimize data calls, optimize Power Fx, use delegation). Test performance with realistic data volumes.
  • UI/UX Inconsistency:
    • Mistake: Designing a custom page that looks completely different from the rest of the model-driven app, leading to a jarring user experience.
    • Avoid: Try to match fonts, colors, and general layout principles of the model-driven app. Use consistent branding elements.
  • Over-reliance on Custom Pages:
    • Mistake: Using a custom page for functionality that could be easily achieved with a standard model-driven form, business rule, or simple JavaScript. This adds unnecessary complexity.
    • Avoid: Evaluate whether a custom page is truly necessary. If a standard form with a few custom controls or business rules can do the job, stick with that. Custom pages are for extended functionality, not basic data entry.
  • Testing Challenges:
    • Mistake: Not thoroughly testing the custom page in different scenarios, with different user roles, and on various devices.
    • Avoid: Test the custom page flow end-to-end. Verify parameter passing, data updates, error handling, and responsiveness. Test with users who have different security roles to ensure they have the correct permissions.

Not read yet

9. Quick Reference: Custom Page Integration Points

Custom pages offer flexibility in how they are presented within your model-driven app. Here's a quick comparison of the main integration points:

Integration Point Description Use Cases Pros Cons
Sitemap Appears as an item in the left navigation pane. Standalone dashboards, full-screen wizards, custom reporting interfaces. Full screen real estate, dedicated experience. Can feel disconnected from specific records.
Dialog Opens as a modal pop-up window over the current screen. Quick edits, confirmation dialogs, multi-step forms directly related to a record. Focused user interaction, keeps context of parent page. Limited screen space, can be intrusive if overused.
Form Tab Embedded directly into a tab on a model-driven form. Displaying related information, custom visualizations tied to a record, interactive sub-forms. Seamless integration with record data, always visible. Fixed size constraints, can slow down form load if complex.
Command Bar Launched from a button on a form or view command bar. Contextual actions on a selected record, initiating workflows, opening related custom pages. Highly contextual, easy to find for relevant actions. Requires Power Fx or JavaScript for dynamic parameter passing.

Not read yet

10. Common Questions (FAQ)

Here are some frequently asked questions about custom pages:

  • Can I use a custom page offline? Yes, if the custom page is designed to work offline (e.g., using the Offline capability of Dataverse tables), it will generally function within the model-driven app's offline capabilities. However, you must explicitly enable offline for the model-driven app and ensure the custom page's data sources are configured for offline use.

  • How do I debug a custom page? You debug a custom page just like any other canvas app. Open the custom page in Power Apps Studio (from your solution). Use the Monitor tool to trace data flows and formula execution. You can also use Notify() messages to display variable values during runtime.

  • Can I embed a custom page within another custom page? No, you cannot directly embed one custom page inside another. However, you can use canvas app components within a custom page to achieve modularity and reuse UI elements and logic. You can also use Host.NavigateTo to move from one custom page to another.

  • What are the licensing implications for custom pages? Custom pages are a feature of Power Apps and require appropriate Power Apps licenses for users. If your custom page connects to premium connectors (e.g., SQL Server, custom connectors), users will need a Power Apps Per App or Per User license. Standard Dataverse access is covered by typical Dynamics 365 or Power Apps licenses.

  • Can a custom page be created outside of a solution? Technically, you can create a canvas app and then convert it to a custom page. However, for proper ALM and to ensure it functions correctly within a model-driven app, you must create and manage custom pages within a solution.

Not read yet

11. Key Takeaways

Custom pages are a game-changer for extending the capabilities and user experience of model-driven apps. By understanding and applying the concepts covered in this lesson, you can build truly powerful and flexible business applications.

Here are the key takeaways:

  1. Custom Pages are Canvas Apps in a Model-Driven Context: They combine the structured data management of model-driven apps with the flexible UI/UX and diverse data connectivity of canvas apps.
  2. The Host Object is Your Gateway: This object (Host.Param, Host.Back, Host.RefreshHost, Host.NavigateTo) is crucial for communication between the custom page and its parent model-driven app.
  3. Parameter Passing is Essential: Use the Data property in the Navigate function (from command bar Power Fx or JavaScript) to pass contextual information (like record IDs) to your custom page. Remember to convert Host.Param() outputs to the correct data types.
  4. Integrate Thoughtfully: Choose the right integration point (sitemap, dialog, form tab, command bar) based on the custom page's purpose and how it fits into the user's workflow. Dialogs are excellent for focused, contextual interactions.
  5. Prioritize Performance and UX: Optimize data calls, use responsive design techniques, and ensure a consistent look and feel with the rest of your model-driven app. Provide clear user feedback.
  6. Always Work in Solutions: For robust application lifecycle management, all custom pages must be created and managed within Power Apps solutions.
  7. Know When to Use Them: Custom pages are best for complex UI, multi-source data, guided processes, or highly interactive experiences that standard model-driven components cannot easily deliver. Avoid using them for simple tasks that existing components can handle.

By mastering custom pages, you gain a powerful tool to create truly compelling and comprehensive business applications that meet even the most demanding user requirements.

Not read yet

Each section gets a ✓ as you scroll through it. Tap the button to jump to the next one.