AX / D365FO – Multiselect lookup on dialog in UI builder class (Sysoperation)

Here is an example of how to use a multi select lookup in a SysOperation class

1. Data contract class: (just showing relevant parameters, there can be other parameters too). Just to note, container type parameter can also be used in place of List.

[DataContract, SysOperationContractProcessing(ClassStr(TestExpImpUIBuilder))]

class TESTEXPDC extends SysOperationServiceBaseDataContract
{
List department;

[DataMemberAttribute, SysOperationLabel("@SYS850"), AifCollectionTypeAttribute('return', Types::String)]
public List parmDepartment(List _department = department)
{
department = _department;

return department;
}
}

2. UI Builder Class: This is most important to build a multi select lookup.

class TestExpImpUIBuilder extends SysOperationAutomaticUIBuilder

{
DialogField dialogDepartment;
SysLookupMultiSelectCtrl ctrlDepartment;

//Override this to add dialog field
protected DialogField addDialogField(IdentifierName _methodName, Object _dataContract = this.dataContractObject())
{
DialogField dialogField;;

switch (_methodName)
{
case methodStr(TESTEXPDC, parmDepartment):
dialogDepartment = this.dialog().addField(
extendedTypeStr(Description),
"@SYS850");
dialogField = dialogDepartment;
break;
default:
dialogField = super(_methodName, _dataContract);
}
return dialogField;
}

//Override this
public void postRun()
{
super();
if (this.dataContractObject() is TESTEXPDC) //if is optional, in my case i was using single UI builder for multiple tasks so required
{
this.lookupDepartment();
}
}

//to populate lookup
protected void lookupDepartment()
{
TableId multiSelectTableNum = tableNum(EcoResCategory);
Query query = new Query();
QueryBuildDataSource qbds = query.addDataSource(multiSelectTableNum);

EcoResCategoryHierarchyRole categoryRole;

select firstonly categoryRole
where categoryRole.NamedCategoryHierarchyRole == EcoResCategoryNamedHierarchyRole::RetailChannelNavigation;

qbds.addRange(fieldNum(EcoResCategory, Level)).value(queryValue(3));
qbds.addRange(fieldNum(EcoResCategory, CategoryHierarchy)).value(queryValue(categoryRole.CategoryHierarchy));
qbds.addSelectionField(fieldNum(EcoResCategory, Code)); //needed for field display in lookup
qbds.addSelectionField(fieldNum(EcoResCategory, Name));

container selectedFields = [multiSelectTableNum, fieldNum(EcoResCategory, Code)]; //irrelevant for lookup but value needed for further use in method calling

ctrlDepartment = SysLookupMultiSelectCtrl::constructWithQuery(this.dialog().dialogForm().formRun(), dialogDepartment.control(), query, false, selectedFields);
}


public void getFromDialog()
{
super();
//keep in mind, multiselect actually brings Recid and works like reference lookup
if (this.dataContractObject() is TESTEXPDC)
{
List listDepartment = new List(Types::String);
container conDeptt = ctrlDepartment.get();

Counter conCount = 1;
Counter conDepLength = conLen(conDeptt);

while (conCount //use sign for less and equal here// conDepLength)
{
listDepartment.addEnd(EcoResCategory::find(conPeek(conDeptt, conCount)).Code);
conCount++;
}
this.dataContractObject().parmDepartment(listDepartment);

//whole list code not needed in case you are using container type parameter
//this.dataContractObject().parmDepartment(ctrlDepartment.get());
}
}
}

3. Service class : Its optional and purely based upon requirement. No lookup code is needed here, just needed for execution type and Contract mapping to further call Task based class.

4. Task class: actual iteration of selected multiselect values would be done here.

class TESTEXPTask

{
List listDepartment;

public static TESTEXPTask construct()
{
return new TESTEXPTask();
}

public void run(TESTEXPDC _contract)
{
this.processDataforExport();
}

protected void processDataforExport()
{
try
{
ttsbegin;
// any code execution

//Line Creation
this.createLinesPerDepartment();
ttscommit;

}
catch (Exception::Error)
{
exceptionTextFallThrough();
}
}

protected void createLinesPerDepartment()
{
if (listDepartment && !listDepartment.empty())
{
ListEnumerator listEnumerator;

listEnumerator = listDepartment.getEnumerator();
while (listEnumerator.moveNext())
{
this.methodName(listEnumerator.current());
}
}
else
{
//call execution code
this.methodeName();
}
}

Leave a comment