Wednesday, 16 September 2020

Multiselect lookup on dialog in UI builder class (Sysoperation) in D365 F&O

 This way of setting Multiselectlookup(Lookup that allows Multiple value selections) can be used on any module (SSRS, Service, Batch or simple server/client based service class) utilizing SysOperation framework. 

Code design would be as follows:- 

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();
        }
    }

and you are done. Just squeeze in your other code like additional parameters and business code and voila!!!

Keep in mind, UI builder class in anyways would be used in similar old manner (overridelookup) for conventional field lookups.

See you in next blog. Happy Daxing (Now D365ing)!!! Please drop a feedback in case of any issues or any other concerns.

27 comments:

  1. It's really Nice Blog!! Thank you for sharing with us..
    DevOps Training
    DevOps Online Training

    ReplyDelete
  2. thanks , that's really good one

    ReplyDelete

  3. For Education,jobs, news, health, Business, Astrology
    http://wisdommaterials.com/
    https://www.globalcompaniesinfo.com/
    http://wisdomallcodes.com

    ReplyDelete
  4. Dynamics 365 for Nonprofits is a solution has been designed keeping the challenges and business structure of such nonprofits in mind. It has proven itself to be the most successful system which is depended upon by numerous nonprofits across the globe. With Dynamics 365 for Nonprofits, you get financial harmony in your operation that is integrated with your email, CRM, and infrastructure. It allows you to unify financials and operations across different charities, funding sources, memberships, and associations, and drive new operational efficiencies to support regulatory compliance and report, automate key functions, and is easy to learn for new volunteers. Get in Touch: ERP for Nonprofits

    ReplyDelete