Interactive UI behaviour in SysOperation Framework

Interactive UI behaviour in SysOperation Framework

So I was working on a batch job recently and needed to toggle a field based on what was selected in another field — both living inside my contract class. Basically, I was after that classic 𝒐𝒏𝑴𝒐𝒅𝒊𝒇𝒊𝒆𝒅 - style behavior. To pull it off, I plugged into the 𝑺𝒚𝒔𝑶𝒑𝒆𝒓𝒂𝒕𝒊𝒐𝒏𝑨𝒖𝒕𝒐𝒎𝒂𝒕𝒊𝒄𝑼𝑰𝑩𝒖𝒊𝒍𝒅𝒆𝒓 class, which lets you mess with the dialog dynamically. If you're curious, there's a solid official Microsoft document for download that deep-dives into the whole SysOperation Framework.


Problem Statement : Dynamically enable or disable a field in real time, depending on the selected value of another field in the contract.


🧩Artefacts at play:

  1. Value changes📥 User changes the value in this field.
  2. Enables or Disables🔄 Gets enabled or disabled based on the value selected in above field.

Both fields live inside my contract class which I will be using in my SysOperation batch job. To wire up dynamic behavior between them — like enabling/disabling based on user input — I spun up a custom class 𝗔𝗕𝗖_𝗖𝘂𝘀𝘁𝗼𝗺𝗨𝗜𝗕𝘂𝗶𝗹𝗱𝗲𝗿 that extends 𝑺𝒚𝒔𝑶𝒑𝒆𝒓𝒂𝒕𝒊𝒐𝒏𝑨𝒖𝒕𝒐𝒎𝒂𝒕𝒊𝒄𝑼𝑰𝑩𝒖𝒊𝒍𝒅𝒆𝒓 like below.

internal final class  ABC_CustomUIBuilder extends SysOperationAutomaticUIBuilder
{
 // Define the fields on class level so we can have global access to the fields
    private DialogField ValueChanges;
    private DialogField EnablesOrDisables;

    public void postBuild()
    {
        super();

// Linking the dialog fields with the parm methods in my contract class
        ValueChanges = this.bindInfo().getDialogField(this.dataContractObject(), methodStr(ABC_CustomContract, parmValueChanges));
        
        EnablesOrDisables = this.bindInfo().getDialogField(this.dataContractObject(), methodStr(ABC_CustomContract, parmEnablesOrDisables));

    }

    public void postRun()
    {
        super();

// This is the main method which is responsible for the modified behaviour
        ValueChanges.registerOverrideMethod(methodStr(FormCheckBoxControl, modified), methodStr(ABC_CustomUIBuilder, New_Modified), this);

    }

// The new method which defines what to do when the field is modified on run time
    public boolean New_Modified(FormCheckBoxControl _control)
    {
        EnablesOrDisables.enabled(ValueChanges.value() == NoYes::Yes);

        return true;
    }

}        

We’ll dissect the code piece by piece, one method at a time.


postBuild()

Inside this method, we’re calling two lines of code that essentially bind our parm methods to DialogField objects. This gives us a direct handle on the dialog controls, so we can do stuff like .𝘦𝘯𝘢𝘣𝘭𝘦𝘥(), .𝘷𝘪𝘴𝘪𝘣𝘭𝘦(), .𝘷𝘢𝘭𝘶𝘦(), etc. Think of it like getting a reference to the actual UI control tied to your contract property.

If you’ve worked with event handlers before, this is kinda like the sender object — where you grab a form control and interact with it dynamically. Here, we're formally binding the contract field to a control in code, so we can tweak its behavior on the fly.

ValueChanges =
this.bindInfo().getDialogField(this.dataContractObject(), methodStr(ABC_CustomContract, parmValueChanges));
        
EnablesOrDisables = this.bindInfo().getDialogField(this.dataContractObject(), methodStr(ABC_CustomContract, parmEnablesOrDisables));        


postRun()

The 𝒓𝒆𝒈𝒊𝒔𝒕𝒆𝒓𝑶𝒗𝒆𝒓𝒓𝒊𝒅𝒆𝑴𝒆𝒕𝒉𝒐𝒅 is the crux of our setup — it’s what gives us the power to plug in custom logic and override standard control events like 𝘤𝘭𝘪𝘤𝘬𝘦𝘥(), 𝘮𝘰𝘥𝘪𝘧𝘪𝘦𝘥(), 𝘷𝘢𝘭𝘪𝘥𝘢𝘵𝘦() and more.

Think of it as a dynamic hook that lets you swap out default behavior with your own method — no need to hardcode stuff on the form. It’s clean, flexible, and keeps the UI layer loosely coupled from the logic.

ValueChanges.registerOverrideMethod(methodStr(FormCheckBoxControl, modified), methodStr(ABC_CustomUIBuilder, New_Modified), this);        


New_Modified(FormCheckBoxControl _control)

This is the custom method we passed as the second parameter in 𝒓𝒆𝒈𝒊𝒔𝒕𝒆𝒓𝑶𝒗𝒆𝒓𝒓𝒊𝒅𝒆𝑴𝒆𝒕𝒉𝒐𝒅. It effectively replaces the standard 𝒎𝒐𝒅𝒊𝒇𝒊𝒆𝒅 method, letting us inject our own behavior whenever the control value changes. The parameter 𝑭𝒐𝒓𝒎𝑪𝒉𝒆𝒄𝒌𝑩𝒐𝒙𝑪𝒐𝒏𝒕𝒓𝒐𝒍 we’ve passed into the method is the actual control instance we’re binding.


Here's how it looks at runtime🚀

When I enable Value Changes the other toggle (Enables or Disables) becomes editable

Article content

When I disable Value Changes the other toggle (Enables or Disables) is blocked.

Article content


What else can I modify ?🤔

Navigate to: 𝑽𝒊𝒔𝒖𝒂𝒍 𝑺𝒕𝒖𝒅𝒊𝒐 ➜ 𝑨𝑶𝑻➜ 𝑺𝒚𝒔𝒕𝒆𝒎 𝑫𝒐𝒄𝒖𝒎𝒆𝒏𝒕𝒂𝒕𝒊𝒐𝒏 ➜ 𝑭𝒐𝒓𝒎𝑪𝒉𝒆𝒄𝒌𝑩𝒐𝒙𝑪𝒐𝒏𝒕𝒓𝒐𝒍

Article content

The Methods section lists all standard event hooks that can be overridden. If you're using a different method for the override, just right-click on it and hit 𝐅𝐢𝐧𝐝 𝐚𝐥𝐥 𝐫𝐞𝐟𝐞𝐫𝐞𝐧𝐜𝐞𝐬 🔍 — it'll show you exactly where and how it's being used across the standard codebase. One example is the 𝑩𝒂𝒏𝒌𝑺𝒕𝒂𝒕𝒆𝒎𝒆𝒏𝒕𝑰𝒎𝒑𝒐𝒓𝒕𝑩𝒂𝒕𝒄𝒉 class as below.

Article content


To view or add a comment, sign in

More articles by Khizar Ansari

  • Complete/Cancel work in X++

    Work in D365FO is used to control, guide and track warehouse activities such as: Picking Put away Replenishment Packing…

  • Create workflow history using X++

    Recently I was working on some customization related to PurchTable workflow in D365FO and I was handling the workflow…

    2 Comments
  • Converting Map to JSON in X++

    If you just need to return a simple JSON, there’s no need to spin up a contract class, you can do it using Maps in X++.…

  • Ship & Receive Transfer Orders in D365FO X++

    Recently I was working on creating, shipping and receiving transfer orders in D365FO. I dug into the menu items that…

  • Understanding Finance & Operations Warehouse App - Part 3

    In part 1 & 2 of this series we saw how the warehouse app functions and what's the framework that handles all the logic…

    1 Comment
  • Consuming REST API in X++

    Recently, I’ve been experimenting with a small proof of concept (POC) to consume an external API using a few available…

  • Create HCM Worker in D365FO

    Recently, I was working on creating workers in D365FO, and it's definitely not as straightforward as it initially…

  • Serializing contract classes using Form JSON Serializer

    When working with SysODataActionAttribute, it's fine to return primitive types but if you try returning a list of JSON…

  • Understanding Finance & Operations Warehouse App - Part 2

    In the previous session, we broke down how the app talks to D365 Finance & Operations via a custom service, with all…

  • Auto Cross Docking in D365 F&O Advance Warehouse Management System (AWMS)

    🔄Most of us are already familiar with the cross-docking process in a warehouse — in simple terms, it lets you fulfill…

    4 Comments

Others also viewed

Explore content categories