Implementing Custom Buttons in Dynamics 365 Forms to Trigger Actions(Plugins)

 

Implementing Custom Buttons in Dynamics 365 Forms to Trigger Actions(Plugins)

Customizing Dynamics 365 to fit specific operational needs often involves extending the user interface with functionalities that streamline and automate tasks. One such enhancement is the integration of custom buttons within entity forms, designed to trigger specific actions seamlessly. This article provides an insight into incorporating a custom button in a Dynamics 365 form, which, upon interaction, executes a predefined action, thereby invoking backend logic or plugins to perform a set of operations.

The Custom Button: A Step-by-Step Overview

The foundation of this customization lies in an HTML web resource, embedding a button directly into the Dynamics 365 form. The button is designed to:

  1. Extract the Current Record Information: A JavaScript function is employed to identify the current record's unique identifier by parsing the form's URL. This ID is crucial for associating the subsequent action with the correct database record.

  2. Initiate the Custom Action: Upon user confirmation, the script dynamically constructs a request targeting a custom action within Dynamics 365, uniquely identified by a generic name (e.g., InvokeCustomAction). This action, associated with the entity in focus, is then called via the Web API.

  3. Response Handling: Following the action call, the script listens for the response. A successful execution leads to a user alert confirming the operation's completion, followed by a form refresh to update the UI accordingly. Conversely, any errors encountered are captured and communicated to the user, enhancing the transparency of the process.

Full Code Example:

<!DOCTYPE html>
<html>
<head>
    <title>Custom Button</title>
    <script>
        function getCurrentRecordId() {
            let parentUrl = parent.window.location.href;
            let url = new URL(parentUrl);
            let recordId = url.searchParams.get("id");
            return recordId ? recordId.replace(/[{}]/g, "") : null;
        }

        async function executeCustomAction() {
            const recordId = getCurrentRecordId();
            if (!recordId) {
                alert("No record ID found.");
                return;
            }

            const actionName = "InvokeCustomAction";
            const userConfirmation = "Proceed with the custom action?";
            if (confirm(userConfirmation)) {
                try {
                    parent.Xrm.Utility.showProgressIndicator("Executing...");

                    const requestUrl = `${parent.Xrm.Utility.getGlobalContext().getClientUrl()}/api/data/v9.0/entities(${recordId})/Microsoft.Dynamics.CRM.${actionName}`;

                    const headers = new Headers();
                    headers.append("OData-MaxVersion", "4.0");
                    headers.append("OData-Version", "4.0");
                    headers.append("Accept", "application/json");
                    headers.append("Content-Type", "application/json; charset=utf-8");

                    const options = {
                        method: "POST",
                        headers: headers,
                        credentials: 'include'
                    };

                    const response = await fetch(requestUrl, options);
                    if (response.ok) {
                        alert("Action executed successfully.");
                        parent.location.reload();
                    } else {
                        throw new Error(`Action failed: ${response.statusText}`);
                    }
                } catch (error) {
                    console.error("Action execution error:", error);
                    alert("Error: " + error.message);
                } finally {
                    parent.Xrm.Utility.closeProgressIndicator();
                }
            }
        }
    </script>
</head>
<body>
    <button onclick="executeCustomAction()">Execute Action</button>
</body>
</html>

Managing Button Visibility with JavaScript

Post-execution, it may be necessary to adjust the UI elements based on the action's outcome, such as hiding the button post-use. This is managed through JavaScript embedded within the main form, executed on form load:

  • The script evaluates the presence of related data or records, such as entries within a specific subgrid (e.g., relatedDataSubgrid).
  • The visibility of the custom button (represented as a web resource, e.g., WebResource_CustomButton) is toggled based on the evaluated condition. If the related data signifies the completion of the intended action, the button is concealed to prevent redundant operations.

function toggleButtonVisibility(executionContext) {
    let formContext = executionContext.getFormContext();

    setTimeout(() => {
        let subgridControl = formContext.getControl("relatedDataSubgrid");
        if (subgridControl) {
            let rowCount = subgridControl.getGrid().getTotalRecordCount();
            let buttonControl = formContext.getControl("WebResource_CustomButton");
            if (buttonControl) {
                buttonControl.setVisible(rowCount === 0);
            }
        }
    }, 1000);
}

No comments:

Post a Comment