Custom Model Driven App Commands

Introduction
Model-driven applications are powerful ways we can allow our end users to interact with business data. In a matter of minutes, we can get an app up and running, which will give access to large collections of data, without having to worry about the record limits or delegation woes of canvas applications. This speed and power come with some limitations to what can be achieved with out-of-the-box model-driven applications. Sometimes you get a requirement that can’t be solved with an out-of-the-box app, this is where we need custom model-driven app commands.
Getting ready to customise
One way to bring customisation to model-driven apps is via the command bar. This post will guide you through creating a custom command to add to a model-driven app. To begin with:
- Navigate to solutions using the left-hand navigation menu, either create a new solution or pick one that already exists.
- Create a model-driven application or choose one that is already in the solution.
- To create an app, choose +New > App > Model Driven App.
- Then give your new app a name

Note from Microsoft Docs
Currently, the command designer can only be accessed through the modern app designer or within solutions for existing commands.
Currently, classic commands can’t be edited within the command designer.
Once you have your model-driven app containing the required Dataverse tables, in-depth information on building model-driven apps, can be found here.
Customising the command bar
To edit the command bar first find the target table, from the Pages section of the app designer.
- Click on the three ellipses next to the chosen table … > Edit Command Bar > Edit.

The next allows us to pick which one of the table command bars we want to add the custom command.
- Main grid – This places the command on the main grid view this is handy when you’re building customisations that will be used either to create a new record or manage multiple records at once.
- Main form – The custom command will be visible on the main forms command bar, handy when you want to enable more custom control over an individual record.
- Subgrid view – Your custom command will be viewable on subgrids when you reference this table within forms from related tables across your application.
- Associated view – Puts a custom command on the command bar of the associated view which can be accessed in the main form from the Related tab.
More information about the different command bar locations can be found here.

In this example, we will add a custom command to the record’s main form. Once selected click edit.

This will open the command designer for our given command bar. To begin with we need to add a command to the bar.
- To do this we will need to click on + New > Command
- This will give the option, to create our new custom command using PowerFx or Javascript.

Power Fx
Power Fx can be used to control not only the action of the command but also its visibility. When this option is chosen the command will have a formula bar similar to that seen in the canvas app development experience. As such when working with Dataverse tables you can use Power Fx formulas as you would when designing canvas app functionality.
Note from Microsoft Docs
Dataverse is currently the only data source supported with commands in model-driven apps.
You can’t currently add additional tables as data sources directly from the command designer. However, you can open the command component library in canvas studio and add additional tables as data sources and then use them within the command designer.
Not all functions available within canvas apps are supported currently for model-driven app commands. Additionally, we’ve introduced some new functions specific to model-driven app commands.
For more limitations with modern commands, go to Modern commanding known limitations.
JavaScript
JavaScript is a high-level, interpreted programming language that is widely used across all aspects of the internet. It is also supported in both modern and classic commands. Modern controls make the process of utilising this robust programming language fairly simple. This guide will create a custom command using JavaScript.
The Command
In this guide, we will make two simple commands. One is a simple HTML screen with a very familiar sentence. The other is possibly more likely to come up when designing amazing solutions for your end users.
HTML Pop Out
For this first example, the command will show an HTML pop-out which displays ‘Hello World’ to the user. To achieve this first we need some web resources, in this example I have used the following for the HTML:
<html lang="en">
<style>
body{
background-color: #f0f0f0;
}
h1{
text-align: center;
margin-top: 100px;
font-size: 50px;
color: #333;
font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif;
}
</style>
<body>
<div>
<h1>Hello World</h1>
</div>
</body>
</html>
Below is the Javascript code, which calls the HTML page.
loadHelloWorld = function() {
var pageInput = {
pageType: "webresource",
webresourceName: "bcdev_helloWorldHTML"
};
var navigationOptions = {
target: 2,
width: 400,
height: 300,
position: 1
};
Xrm.Navigation.navigateTo(pageInput, navigationOptions).then(
function success() {
// Handle dialog closed
console.log("Inside Success");
},
function error() {
Xrm.Navigation.openAlertDialog({ text: error.message });
}
);
}
- With the new command added to the bar, we need to name it.
- An optional extra is associating a web resource icon for the command to give it visual uniqueness.

- Then under ‘Action’ select ‘Run JavaScript’
- Choose the web resource library that you want to use. Please note that the list you will see contains all the libraries currently in use.
- To add a new library click + Add Library
- Search for the library you wish to use and click Add.

- Enter the name of the function being called.
- Add the following parameter:
- PrimaryControl (identifier for the control)
- Click save + publish.

With that, the command is complete, open your updated model-driven app, navigate to a record and click the newly created custom command:

Canvas Page PopOut
Loading custom HTML pages is one thing, though what about a modal dialogue box, a pop-up that allows users to input information against a given record? We shall take a look at this next, creating a custom page which we will use to interact with one of our records.
Custom page
First, let’s walk through, the process of creating the custom page for our model-driven app.
- To do this we need to click on + New > App > Page

Once the design studio is open, the first step is to change the canvas size to our preferred height and width.

With this done we have a blank canvas to create the layout of our modal dialogue box. For this example, I have added some inputs which will display the book title and author. Though more importantly for this demo, allow end users to enter notes on the book record selected.

Next, select the App level in the left-hand tree view, and choose the ‘OnStart’ property from the drop-down menu in the formula bar. We need to enter the following code into this property:
Set(
gblBookDetails,
GUID(Mid(Param("recordId"),2, Len(Param("recordId"))-2))
);
Set(
gblBook,
LookUp(BookInformations,
BookInformation = gblBookDetails
)
);
If you’re following this post and are seeing an error which says “Name isn’t valid. ‘BookInformations’ isn’t recognized” this is because we are still needing to add the Book Information table to the page.
- This is done on the Data menu. Click Data > + Add data > choose the table you need.

To display the values in both the Title and Author text inputs, we set the value property in both to the following:
gblBook.Title
gblBook.Author


Along with the Title and Author inputs, I also added a multi-line text input to capture any notes the end users wish to add to the record. To round off this custom app page, we simply need to add two buttons, one to submit the notes back to the record, and the other to cancel and close the popout window.
For the Submit button the following code needs to be added to the ‘OnSelect’ property:
Patch(
BookInformations,
gblBook,
{
Notes: txtNotesFormContentHome.Value
}
);
Back();

The Cancel button needs a single line of text to close the pop-out window.
Back();

Adding the control
Adding the control button to the command bar follows the same steps as the HTML pop-out, the difference here is that we will be using a different web resource library. The JavaScript below is what we shall use to call the custom page and then display it to the end user.
function loadCustomHelloWorld(PrimaryControl, FirstSelectedItemId, SelectedEntityTypeName){
var pageInput = {
pageType: "custom",
name: "bcdev_custompagepopout_d30d9",
entityName: SelectedEntityTypeName,
recordId: FirstSelectedItemId
};
var navigationOptions = {
target: 2,
position: 1,
height: 800,
width: 600,
title: "Edit Notes"
};
Xrm.Navigation.navigateTo(pageInput, navigationOptions).then(
function () {
PrimaryControl.data.refresh();
// This refreshes the form after the dialog is closed to show the updated data
}
).catch (
function (error) {
// Handle error
}
);
}
The other difference between this example and the previous one is the parameters that are passed to the JavaScript from the custom control.

These are:
- PrimaryControl (identifier for the control)
- FirstPrimaryItemId (This is the GUID to the record)
- SelectedEntityTypeName (This is the name of the table the record is from)
Once the control has been added, it is important to remember to add your custom page to the model-driven application.
- Click ‘+ Add page’ > ‘Custom Page’

When adding your custom page, if it is not meant to be accessible directly from the navigation pane on the left of you’re model-driven application, remember to un-check ‘Show in navigation’.

For this example, I’ve added a notes field to the form shown in the application, using the new custom command will allow my end users to amend the notes section.


Using FirstPrimaryEntityId allows details from the selected record to be passed to and from the custom page. Once the notes have been completed clicking Submit on the custom pop-out will save this information back to the record using the Patch command.

Conclusion
So there we have it, creating custom controls for your model-driven apps. Although out-of-the-box model-driven apps offer excellent functionality, incorporating custom commands can significantly enhance your users’ experience. I hope this post has provided valuable insights and practical guidance for integrating custom commands into your next project, elevating the overall performance and user satisfaction of your model-driven apps.
If you liked this post why not check out ‘Power Apps – Sending Outlook Emails in Canvas Apps’
Leave a comment