Skip to main content

Notifications

D365 F&O How to Copy to Clipboard and Assign Hot Keys

I had a task to copy the product items numbers separated by comma that are shown on the grid to the to the clipboard when an User clicks the specific button. Also I would like to assign a hot key to this button. Both tasks have been implemented with the help of Extensible control see details below.

Why Extensible control? It is because the clipboard and hot keys are client side resources. To implement the client side logic X++ can not be used, since it has no access to the client’s resources.

In my case I use X++ to prepare a string that contains product items separated by comma that is shown on the form grid, while the Extensible control is used to add client side logic to copy the string to the clipboard and assign hot key.

To simplify the X++ logic lets assume there is a form with a released products grid with one CopyButton button. The CopyButton button should copy product ids separated by comma to the clipboard.

There is no code in the CopyButton.clicked() method.

Add an extensible control to the form

Create a new PIMCopyControl extensible control.

Create a new class that is inherited form the FormTemplateControl class:

  • Specify a path to HTML resource that will be created a bit later
  • Create a new getProducts() method – place the code that was planned to be in the CopyButton.clicked() method. In my case the code will return the list of products separated by comma.
    Note that there is an access to the formRun, so you can create a new method on the form / form extension (the method can use all form objects: datasources, form variables etc) and call it from extensible control method.
[FormControlAttribute('PIMCopyControl','/Resources/html/PIMCopyControl', classStr(PIMCopyControlBuild))]
internal final class PIMCopyControl extends FormTemplateControl
{
    public void new(FormBuildControl _build, FormRun _formRun)
    {
        super(_build, _formRun);
 
        this.setTemplateId('PIMCopyControl');
        this.setResourceBundleName('/Resources/html/PIMCopyControl');
    }

    [FormCommandAttribute("getProducts")]
    public str getProducts()
    {
        Object formObject = this.formRun();
        str products = formObject.copySelectedProducts();

        return products;
    }

}

Create a new class that is inherited form the FormBuildControl class. It allows you to add the new control on the form.

[FormDesignControlAttribute('PIMCopyControl')]
internal final class PIMCopyControlBuild extends FormBuildControl
{
}

Add the extensible control to the form.

Add js and html files

Create an empty files with .html and .js file extension. Add new Resources to the project, select the file on the Add new item form and repeat adding with another file.

Add new code to the .html file:

<script src="/resources/scripts/PIMCopyControl.js"></script>
<div id="PIMCopyControl" class="copyControl" data-dyn-bind="visible: $data.Visible"></div>

The html file contains an empty <div> with several attributes. It works without this <div> as well, but error behind the scene is generated by the Dynamics365F&O JavaScript function that control doesn’t have a template.

Add new code the the .js file:

(function () {
    'use strict';
    $dyn.ui.defaults.PIMCopyControl = {};

    $dyn.controls.PIMCopyControl = function (data, element) {
        var self = this;

        $dyn.ui.Control.apply(self, arguments);
        $dyn.ui.applyDefaults(self, data, $dyn.ui.defaults.PIMCopyControl);

        self.getProductsCallBack = function (_sJSON) {
            navigator.clipboard.writeText(_sJSON);
        }
    }

    $dyn.controls.PIMCopyControl.prototype = $dyn.extendPrototype($dyn.ui.Control.prototype,
    {
        init: function (data, element) {
            var self = this;
            $dyn.ui.Control.prototype.init.apply(this, arguments);

            var elemm = document.getElementsByName('CopyButton')[0];
            elemm.onclick = function () {
                $dyn.callFunction(self.getProducts, self, {}, self.getProductsCallBack);
            };
        }
    });

    // Keep track of clicked keys
    var isKeyPressed = {
        q: false, // ASCII code for 'q'
        w: false // ASCII code for 'w'
        // ... Other keys to check for custom key combinations
    };

    document.onkeydown = keyDownEvent => {
        //Prevent default key actions, if desired
        //keyDownEvent.preventDefault();

        // Track down key click
        if (keyDownEvent.key == "q" || keyDownEvent.key == "w") {
            isKeyPressed[keyDownEvent.key] = true;
        }

        // Check described custom shortcut
        if (isKeyPressed["q"] && isKeyPressed["w"]) {
            var elemm = document.getElementsByName('CopyButton')[0];
            if (elemm) { elemm.click(); }
        }
    };

    document.onkeyup = keyUpEvent => {
        // Prevent default key actions, if desired
        //keyUpEvent.preventDefault();

        // Track down key release
        if (keyUpEvent.key == "q" || keyUpEvent.key == "w") {
            isKeyPressed[keyUpEvent.key] = false;
        }
    };

})();

The JavaScript function will be called when the form with extensible control is loaded at first time. Each time the form is opened the DOM is rebuild. The control prototype Init method is called each time the form is opened. So the Init method is used to add a custom logic.

The $dyn.callFunction(funcName) is used to call serves side (X++) function. The self.funcNameCallBack is used to handle the result of the called function (the _sJSON variable contains the variable returned by the X++ method).

The $dyn class contains javascripts classes that are implemented to visualize standard D365 F&O in a browser.

To access the CopyButton the following code is used: document.getElementsByName(‘CopyButton’)[0]

There are other articles about extensible control:
https://samidax.wordpress.com/2020/06/28/extensible-control-in-d365-fo/
https://dev.goshoom.net/2016/12/extensible-control-htmljavascript/

Summary

The standard CopyButton button is used just to create an UI element on the form (to avoid creating this element via html, css manually in Extensible control).

The Extensible control is used to add a business logic to the CopyButton button. The Extensible control is just an empty <div> block on UI.

The post D365 F&O How to Copy to Clipboard and Assign Hot Keys first appeared on Dynamics AX Training.

This was originally posted here.

Comments

*This post is locked for comments