To create custom HTML control in Dynamics 365 for Operations you will need to create:
As an example, we will be creating custom control to sort table records in a drag & drop style. D365 is using jQuery and we will use Sortable control as a UI base for our new custom control. The name of new custom control will be VKOSortableList.
Build class allows to define the properties that appear in the Visual Studio property sheet.
It allows to create following types of parameters, which then will be displayed by VS in form designer:
Build class also will be used as a contract class to fetch defined properties in run-time class.
Build class for VKOSortableList will contain following properties:
Build class for VKOSortableList control can be downloaded using following link:
VKOSortableListBuild.txt
Contract, which is used to describe sortable item. There we need two properties, one is "text" to show in UI and second one is recId to identify the record:
/// <summary> /// The contract to store sortable item information. /// </summary> [DataContractAttribute] class VKOSortableListItem { str text; ReFRecId recId; [DataMemberAttribute("text"), FormDesignPropertyAttribute("text", "Data")] public str parmText(str _text = text) { if(!prmisDefault(_text)) { text = _text; } return text; } [DataMemberAttribute("recId"), FormDesignPropertyAttribute("recId", "Data")] public RefRecId parmRecId(RefRecId _recId = recId) { if(!prmisDefault(_recId)) { recId = _recId; } return recId; } }
The run-time class defines server-side business logic.
FormControlAttribute class attribute is used to define:
Control framework uses FormProperty for the synchronization of property values between X++ and JavaScript.
Common use of FormProperty:
Typical run-time class should contain following methods:
VKOSortableList run-time class contains additional methods to load sortable item blokcks from given data source and save order of records. It can be downloaded using following link:
It is entry point for web UI. Should contain HTML template and may contain any number of links to JavaScript or/and CSS resources if you need them.
Please be aware that there could be more than one instance of your control at same page. Control framework gracefully controls load of additional resources, which are stated in HTML template. They will be loaded only once. Also, it means that inline JavaScript will be executed only once. Bear that in mind and encapsulate all JavaScript logic required for custom control operation in object named same as Template-ID.
HTML template for VKOSortableList control:
<ul id="VKOSortableList" data-dyn-bind="visible: $data.Visible, sizing: $dyn.layout.sizing($data), foreach: $data.SortableItems" > <li class="ui-state-default ui-sortable" data-dyn-bind="text: $data.text, attr: {recid: $data.recId}">Item 1</li> </ul> <script src="/resources/scripts/VKOSortableListControlJS.js"></script> <link href="/resources/styles/VKOSortableListControlCSS.css" rel="stylesheet" type="text/css" />
Please take a note that:
data-dyn-bind - handles many common DOM manipulations. There is short description of data-dyn-bind capabilities:
More information can be found following next link.
.ui-state-default { border: 1px solid #c5c5c5; background: #f6f6f6; font-weight: normal; color: #454545; text-decoration: none; } .ui-sortable { list-style-type: none; height: 25px; width: 100%; margin-top: 3px; padding: 4px; }
In our case JavaScript part is quite simple as majority of UI interaction is handled by jQuery Sortable control. We are simply initiating Sortable control for a given element and subscribing to control’s update event, which is triggered when item block is dropped. We need it to grab the current order of blocks and pass this information to server side to save new record order.
// As a best practice, wrap your code in function like this to protect the 'global namespace'. // Also as a best practice, use strict to catch common JS errors. (function () { 'use strict'; $dyn.ui.defaults.VKOSortableList = { jqSortable: null }; $dyn.controls.VKOSortableList = function (props) { var self = this; // Almost all controls 'extend' the Control base class. This syntax is used to call the contructor for the base class. $dyn.ui.Control.apply(this, arguments); $dyn.ui.applyDefaults(this, props, $dyn.ui.defaults.VKOSortableList); var SortableItems = $dyn.peek(self.SortableItems); console.log(SortableItems); self.sortChange = function (event, ui) { console.log('------'); var sequenceArr = new Array(); $.each(this.jqSortable.find("li"), function (key, val) { console.log("item key: " + key + " - data: " + $(val).attr('recid') + " - text: " + $(val).text()); sequenceArr.push($(val).attr('recid')); }); if ($dyn.callFunction) { $dyn.callFunction(self.OrderModified, self, [sequenceArr.join()], function () { /* executes on success */ }); } }; self.applyContext = function (Func, Context) { return function () { return Func.apply(Context, arguments); } }; self.jqSortable = $(props._element).sortable({ update: self.applyContext(this.sortChange, this) }); }; $dyn.controls.VKOSortableList.prototype = $dyn.extendPrototype($dyn.ui.Control.prototype, { }); })();
To see our newly created control in action we need to create a test form. VKOSortableList control will automatically appear in the list of controls:
VKOSortableTable is a simple table with two fields:
As a result, we will have following look in web browser, where we are able to sort records using drag & drop style:
Modern web browsers (including Edge and Chrome) have powerful developer tools. It can give you all aspects of information about HTML structure, CSS tables acting on elements, JavaScript console.
In Visual Studio, you can select preferable web browser to use:
Dynamics 365 -> Options -> Default browser to use when running projects drop down will have a list of installed browsers. Google Chrome and Edge/Internet Explorer currently supported.Please be aware that you can use console.log(anytype) to output values to web browser’s console and then investigate value. It can handle complex objects such as arrays/objects/DOMelements.
In Google Chrome, you can access developer’s tools by pressing ctrl+shift+I (menu->Moretools->Developer tools) and then click console tab:
In Internet Explorer, you can do it by pressing F12
DaxOnline.org is free platform that allows you to quickly store and reuse snippets, notes, articles related to Dynamics AX.
Authors are allowed to set their own AdSense units and "buy me a coffee" link.
Join us.