Side Pane Development:
To develop and extend a side pane, you can use the following methods:
createPane
:
This method is used to create a side pane. Below are the properties of the object used for configuring the pane during its creation:
title |
The title of the pane, displayed in the pane header and tooltip. |
---|---|
paneId |
The unique identifier for the pane. If not provided, an ID will be automatically generated. |
canClose |
Determines if the pane header will include a close button. Defaults to false . |
imageSrc |
The file path for the icon shown in the panel switcher control. |
hideHeader |
Controls the visibility of the pane header, including the title and close button. Defaults to false . |
isSelected |
If set to false , the pane will not be selected, leaving the currently selected pane active. The pane will also remain collapsed if it was previously collapsed. |
width |
The width of the pane in pixels. |
hidden |
Specifies whether the pane and its tab should be hidden. |
alwaysRender |
Ensures the pane remains rendered even when hidden, preventing it from unmounting. |
keepBadgeOnSelect |
Prevents the badge from being cleared when the pane is selected. |
getAllPanes
Returns a collection containing all active panes.
Xrm.App.sidePanes.getAllPanes();
getSelectedPane
Returns the current selected pane.
Xrm.App.sidePanes.getSelectedPane();
getPane
Returns the pane corresponding to the specified ID. If the pane does not exist, undefined
is returned.
Xrm.App.sidePanes.getPane(panelId);
You can add any of the following three pageType
to the pane.navigate
method of side pane creation:
entityrecord
entitylist
webresource
To demonstrate these types of pages, I’ve added a dropdown command button to the account form. When the dropdown is expanded, it displays three buttons. Each button triggers a different function from my JScript library when clicked.
entityrecord
Using this method, you can open another record in the side pane. Since it uses the record ID (GUID) to open the record, you can access records of any entity. For example, if you want to open the primary contact record in the side pane from the account form, you can use the entity record page in the side pane. Below is the code to implement this example.
function sidePaneForm(primaryControl) {
var formContext = primaryControl;
var primaryContactId = formContext.getAttribute("primarycontactid") === (null || undefined) ? null : formContext.getAttribute("primarycontactid").getValue()[0].id.replace("{", "").replace("}", "");
Xrm.App.sidePanes.createPane({
title: "Primary Contact",
imageSrc: "WebResources/sample_reservation_icon",
paneId: "PrimaryContactPane",
canClose: true
}).then((pane) => {
pane.navigate({
pageType: "entityrecord",
entityName: "contact",
entityId: primaryContactId
})
});
}
Below is a snapshot of the demonstration.
entitylist
This type of page will display views for the specific entity mentioned in the code. For example, if you want to open a list of contacts in the side pane, you can use the entity list page to achieve this. Below is the code for implementing this example
function sidePaneList() {
Xrm.App.sidePanes.createPane({
title: "Accounts",
imageSrc: "WebResources/sample_reservation_icon",
paneId: "AccountsListPane",
canClose: true
}).then((pane) => {
pane.navigate({
pageType: "entitylist",
entityName: "account",
})
});
}
Below is a snapshot of the demonstration.
webresource
With this type of side pane, you can display an HTML web resource. The page type should be set to webresource
. For example, you can open an HTML page with custom scripting. Below are code snippets to demonstrate this.
HTML Code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Custom List Page</title>
<link rel="stylesheet"
href="<https://static2.sharepointonline.com/files/fabric/office-ui-fabric-js/1.4.0/css/fabric.min.css>" />
<link rel="stylesheet"
href="<https://static2.sharepointonline.com/files/fabric/office-ui-fabric-js/1.4.0/css/fabric.components.min.css>" />
<script src="<https://static2.sharepointonline.com/files/fabric/office-ui-fabric-js/1.4.0/js/fabric.min.js>"></script>
<script src="ClientGlobalContext.js.aspx" type="text/javascript"></script>
<script>
function onCollapseOfSidePane() {
var primaryContactId, nameSplit, nameInitial;
if (location.search != null) {
if (location.search.split("=")[1] != null) {
primaryContactId = decodeURIComponent(location.search.split("=")[1]);
Xrm.WebApi.retrieveRecord("contact", primaryContactId, "?$select=fullname,emailaddress1,telephone1").then(
function success(result) {
document.getElementById("fullName").innerText = result.fullname;
document.getElementById("emailAddress").innerText = result.emailaddress1;
document.getElementById("mobileNumber").innerText = result.telephone1;
// split the fullname to get first letters for initials
nameSplit = result.fullname.split(" ");
nameInitial=nameSplit[0][0]+nameSplit[nameSplit.length-1][0];
document.getElementById("nameInitial").innerText = nameInitial.toUpperCase();
},
function (error) {
console.log(error.message);
}
);
}
}
}
window.onload = onCollapseOfSidePane();
</script>
</head>
<body>
<h1 class="ms-Label">Primary Contact</h1>
<div class="ms-Grid-col ms-sm12 ms-md12 ms-lg12">
<div class="ms-Persona ms-Persona--lg">
<div class="ms-Persona-imageArea">
<div class="ms-Persona-initials ms-Persona-initials--blue" id="nameInitial"></div>
</div>
<div class="ms-Persona-details">
<div class="ms-Persona-primaryText" id="fullName"></div>
<div class="ms-Persona-secondaryText" id="emailAddress"></div>
<div class="ms-Persona-secondaryText" id="mobileNumber"></div>
</div>
</div>
</div>
<script type="text/javascript">
var PersonaElements = document.querySelectorAll(".ms-Persona");
for (var i = 0; i < PersonaElements.length; i++) {
new fabric['Persona'](PersonaElements[i]);
}
</script>
</body>
</html>
JScript Code:
function sidePaneCustom(primaryControl) {
var formContext = primaryControl;
var primaryContactId = formContext.getAttribute("primarycontactid") === (null || undefined) ? null : formContext.getAttribute("primarycontactid").getValue()[0].id.replace("{", "").replace("}", "");
sweepPanes();
Xrm.App.sidePanes.createPane({
title: "Contacts List",
imageSrc: "WebResources/sample_reservation_icon",
paneId: "CustomListPagePane",
canClose: true
}).then((pane) => {
pane.navigate({
pageType: "webresource",
webresourceName: "crf4c_customListPage",
data: primaryContactId
})
});
}
We can use a data field to pass values through URL parameters, which can then be retrieved in the HTML web resource.
Below is a snapshot of the demonstration.
And More…
You can close the pane programmatically using the code below.
Xrm.App.sidePanes.getPane(panelId).close();
Also, you call collapse or expand the side pane programmatically by using the code below. Where 0
is to collapse and 1
is to expand.
Xrm.App.sidePanes.state = 0;
Closing the Opened Panes:
In a scenario where you have multiple side pane on a single page, improper closure of panes can result in a cluttered side navigation. To avoid this, it’s better to use a function to close any open panes before opening a new one and call this method before every side pane creation. You can achieve this by using the getAllPanes().getAll()
method to retrieve all currently open panes on the page. Below is the code to close all open panes.
function sweepPanes() {
var ourPaneArray = ["PrimaryContactPane", "AccountsListPane", "AccountsListPane"];
var paneArray = Xrm.App.sidePanes.getAllPanes().getAll();
paneArray.forEach(function (pane) {
if (ourPaneArray.includes(pane._paneId)) {
Xrm.App.sidePanes.getPane(pane._paneId).close();
}
});
}
Have a great day!