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.
- Create the Form: Create a new Form named
CustLookupForm. - Apply Form Pattern:
Right-click the Design node → Apply Pattern → Lookup Basic. - Data Sources:
- Add
CustTable - Add
DirPartyTableand join it to CustTable - Set AllowEdit, AllowCreate, AllowDelete to No
- Add
- Design Properties:
Set Style =Lookup. - Grid Layout:
The Lookup Basic pattern requires:
Design → Group → Grid - Form Logic (init):
- Form Logic (run): Handle filtering
public void init()
{
super();
element.selectMode(CustTable_AccountNum); // Returns the row's value to caller when clicked
}
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