Show Dynamics 365 Account Contacts in Side Panel HTML Table

Create a JavaScript webresource

Create a JavaScript webresource with the below Code.

var APY = APY || { namespace: true };
APY.Account = APY.Account || { namespace: true };
APY.Account.LoadPromotions = function (executionContext) {
    "use strict";
    try {
        var formContext = executionContext.getFormContext();
        var qs = "accountid=" + formContext.data.entity.getId().replace('{', '').replace('}', '');
        Xrm.App.sidePanes.createPane({
            title: "Contacts",
            paneId: "ContactList",
            canClose: true
        }).then((pane) => {
            pane.navigate({
                pageType: "webresource",
                webresourceName: "cr235_SidePane.html",
                data: encodeURIComponent(qs)
            });
        });
    }
    catch (e) {
        APY.Common.ShowAlertDialog("Ok", e.message + "An error occured. Please contact your System Administrator", "Error Dialog");
    }
};

Web Resource: Side Pane JS

Create an Html web resource

Create an Html web resource with the below code.

<html>
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <style>
        table {
            font-family: arial, sans-serif;
            border-collapse: collapse;
            width: 100%;
        }
        td, th {
            border: 1px solid #dddddd;
            text-align: left;
            padding: 8px;
        }
        tr:nth-child(even) {
            background-color: #dddddd;
        }
    </style>
    <script>
        var Xrm = null;

        function loadContacts() {
            debugger;
            Xrm = parent.Xrm;
            var serverURL = Xrm.Page.context.getClientUrl();
            var id = Xrm.Page.data.entity.getId();
            var fetchXml = "<fetch mapping='logical' output-format='xml-platform' version='1.0' distinct='false'>" +
                "  <entity name='contact'>" +
                "    <attribute name='fullname' />" +
                "    <attribute name='firstname' />" +
                "    <attribute name='lastname' />" +
                "    <order descending='false' attribute='fullname' />" +
                "    <filter type='and'>" +
                "      <condition value='" + id + "' attribute='parentcustomerid' uitype='account' uiname='Test' operator='eq' />" +
                "    </filter>" +
                "  </entity>" +
                "</fetch>";

            var encodedFetchXML = encodeURIComponent(fetchXml);
            var req = new XMLHttpRequest();
            req.open("GET", Xrm.Page.context.getClientUrl() + "/api/data/v9.1/contacts?fetchXml=" + encodedFetchXML, false);
            req.setRequestHeader("OData-MaxVersion", "4.0");
            req.setRequestHeader("OData-Version", "4.0");
            req.setRequestHeader("Accept", "application/json");
            req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
            req.setRequestHeader("Prefer", "odata.include-annotations=\"*\"");
            req.onreadystatechange = function () {
                if (this.readyState === 4) {
                    req.onreadystatechange = null;
                    if (this.status === 200) {
                        var results = JSON.parse(this.response).value;
                        debugger;
                        if (results.length > 0) {
                            for (let i = 0; i < results.length; i++) {
                                var html = "<tr><td><p onclick='productClicked(" + results[i].firstname + ");' style='cursor: pointer;text-decoration: underline;color: blue;'>" + results[i].lastname + "</p></td><td>" + results[i].fullname + "</td></tr>";
                                $("#contactsLists").append(html);
                            }
                        } else {
                            Xrm.Utility.alertDialog(this.statusText);
                        }
                    }
                }
            };
            req.send();
        }

        function productClicked(ProductNumber) {
            console.log(ProductNumber);
        }
    </script>
    <meta charset="utf-8">
</head>
<body onload="loadContacts()" onfocusout="parent.setEmailRange();" style="overflow-wrap: break-word;">
    <table>
        <thead>
            <tr>
                <th>Contact</th>
                <th>Information</th>
            </tr>
            <tr>
            </tr>
        </thead>
        <tbody id="contactsLists">
        </tbody>
        <tbody>
        </tbody>
    </table>
</body>
</html>

HTML Table

We are required to invoke the JavaScript function (APY.Account.LoadPromotions) on various events such as OnLoad, OnChange, OnSave, or Ribbon Button Click.

I have registered the event on the OnLoad of the form with APY.Account.LoadPromotions.

Set up an event for the Account entity onload

After creating web resources, set up an event for the Account entity onload, as shown in the screenshot below.

Form properties

Handler properties

Generate records for contacts

Generate records for contacts related to an Account.

Records

Contacts

Explore additional styles for displaying the Navigation side pane with the link: https://www.c-sharpcorner.com/article/side-pane-with-entity-form-in-dynamics-365/


Similar Articles