Thursday, December 11, 2025

D365F&O: Create and Use Custom Lookups (Updated Guide)

D365F&O: Create and Use Custom Lookups

In this article, we will cover how to create a lookup form and link it with an EDT or String field in Dynamics 365 Finance & Operations using Extensions and Chain of Command.

Technical Prerequisites

  • Chain of Command (CoC): We will use extension classes to override form control behavior.
  • Form Patterns: We will use the "Lookup Basic" pattern to ensure the form renders correctly as a popup in the web browser.

Scenario

We need to override the system lookup to apply custom logic, filters, or use a completely custom Form design as a lookup for a specific field.


1. Standard String/EDT Field Lookup (via Chain of Command)

Use this when you want to filter a specific field using X++ query logic without creating a new custom lookup form.

Class: Form Data Source Field Extension

// Override lookup for CustGroup field
[ExtensionOf(formDataFieldStr(CustTable, CustTable, CustGroup))]
final class CustTableFormDataField_Extension
{
    public void lookup(FormControl _formControl, str _filterStr)
    {
        Query query = new Query();
        QueryBuildDataSource qbds;
        SysTableLookup sysTableLookup;

        // Lookup on CustGroup table (Correct)
        sysTableLookup = SysTableLookup::newParameters(tableNum(CustGroup), _formControl);

        // Fields to show
        sysTableLookup.addLookupfield(fieldNum(CustGroup, CustGroup));
        sysTableLookup.addLookupfield(fieldNum(CustGroup, Name));

        // Build query
        qbds = query.addDataSource(tableNum(CustGroup));

        // Optional filtering example:
        // qbds.addRange(fieldNum(CustGroup, CustGroup)).value("10*");

        sysTableLookup.parmQuery(query);
        sysTableLookup.performFormLookup();
    }
}

2. Reference Group Lookup (RecId-based fields)

This applies when the lookup control is a Reference Group and you want to override its lookup logic.

Class: Form Control Extension

// Example control name: PayrollEarningCode
[ExtensionOf(formControlStr(HcmPosition, PayrollEarningCode))]
final class HcmPosition_PayrollEarningCode_Extension
{
    public Common lookupReference()
    {
        Query query = new Query();
        QueryBuildDataSource qbds;
        SysReferenceTableLookup sysRefTableLookup;

        FormReferenceGroupControl referenceControl = this;

        sysRefTableLookup = SysReferenceTableLookup::newParameters(
            tableNum(PayrollEarningCode),
            referenceControl
        );

        sysRefTableLookup.addLookupfield(fieldNum(PayrollEarningCode, EarningCode));
        sysRefTableLookup.addLookupfield(fieldNum(PayrollEarningCode, QuantityUnit));

        qbds = query.addDataSource(tableNum(PayrollEarningCode));

        sysRefTableLookup.parmQuery(query);

        return sysRefTableLookup.performFormLookup();
    }
}

3. Using a Custom Form as a Lookup

Use this method when you have built a custom lookup form (e.g., CustLookupForm) for complex UI behavior.

Class: Form Control Extension

[ExtensionOf(formControlStr(SalesTable, CustAccount))]
final class SalesTable_CustAccount_Extension
{
    public void lookup(FormControl _formControl, str _filterStr)
    {
        Args args = new Args();
        FormRun custLookup;

        args.name(formStr(CustLookupForm)); // Custom lookup form name
        args.caller(_formControl);

        custLookup = classFactory.formRunClass(args);
        custLookup.init();
        custLookup.run(); // Recommended for stability

        _formControl.performFormLookup(custLookup);
    }
}

How to Design a Lookup Form in D365

A lookup form must follow specific design patterns to render correctly in the browser.

  1. Create the Form: Create a new Form named CustLookupForm.
  2. Apply Form Pattern:
    Right-click the Design node → Apply PatternLookup Basic.
  3. Data Sources:
    • Add CustTable
    • Add DirPartyTable and join it to CustTable
    • Set AllowEdit, AllowCreate, AllowDelete to No
  4. Design Properties:
    Set Style = Lookup.
  5. Grid Layout:
    The Lookup Basic pattern requires:
    Design → Group → Grid
  6. Form Logic (init):
  7. public void init()
    {
        super();
        element.selectMode(CustTable_AccountNum); // Returns the row's value to caller when clicked
    }
    
  8. Form Logic (run): Handle filtering
  9. public void run()
    {
        FormStringControl callerControl;
        boolean filterLookup;
    
        callerControl = SysTableLookup::getCallerStringControl(element.args());
    
        // Filter before run()
        filterLookup = SysTableLookup::filterLookupPreRun(
            callerControl,
            CustTable_AccountNum,
            CustTable_ds
        );
    
        super();
    
        // Apply filter after form loads
        SysTableLookup::filterLookupPostRun(
            filterLookup,
            callerControl.text(),
            CustTable_AccountNum,
            CustTable_ds
        );
    }
    

No comments:

Post a Comment

Search This Blog