Monday, August 6, 2018

D365FO - TableGroupAll dynamic lookup based on previous field example

The following is an example of how to add in a lookup field to a form that will change sources of the lookup depending on a previous selection. In the example below we a mandatory field that has to be filled in before it can be inserted into a table however the field that needs to be filled in will be populated by a dropdown from either CustomCustomerAccountView or CustomCustomerGroupsView which is determined by a previous field in the datasource. The value that will be saved will be of two different edt types or blank but saved within the same field. This utilizes the idea behind the default Enum TableGroupAll which allows the user to select a Table, GroupId or All as an enum value and then the user selects something that is of type table(specific), group or all.

Our detailed scenario:

Form Details:
Custom form called MyCustomForm which we need need to look at the control MyCustomForm_AccountCode to determine what the lookup for MyCustomForm_AccountSelection will show.

Table Details:
Table: MyCustomRuleTable  - this is where the value of AccountCode(enum TableGroupAll) and AccountSelection (lookup value) will be saved

Lookup Details:
TableGroupAll::Table = pull the data from CustomCustomerAccountView and save the customer account id
TableGroupAll::GroupId = pull the data from CustomCustomerGroupsView and save the customer group id
TableGroupAll::All = do not allow the user to select anything and the value should be blank

This field will be in a grid value so we need to also determine when to enable/disable the selection field as well as marking the field as mandatory.



[ExtensionOf(formStr(MyCustomForm))]
final class MyCustomForm_Extension
{
    /// <summary>
    /// Lookup code for account selection based on TableGroupAll selection
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    [FormControlEventHandler(formControlStr(MyCustomForm, MyCustomForm_AccountSelection), FormControlEventType::Lookup)]
    public static void MyCustomForm_AccountSelection_OnLookup(FormControl sender, FormControlEventArgs e)
    {
        Query query = new Query();
        QueryBuildDataSource queryBuildDataSource;
        SysTableLookup sysTableLookup;
        FormRun formRun;
        FormControl formControl;
        TableGroupAll accountCodeType;

        //get the value the account code selection
        formRun = sender.formRun();
        formControl = formRun.design().controlName(formControlStr(MyCustomForm, MyCustomForm_AccountCode));

     

        // check to see what the value of the account code field is to determine what lookup table we should use
        if(str2Enum(accountCodeType, formControl.valueStr()) == TableGroupAll::Table)
        {
            //look up that shows the customer number and name
            sysTableLookup = SysTableLookup::newParameters(tableNum(CustomCustomerAccountView),sender,true);
            sysTableLookup.addLookupfield(fieldNum(CustomCustomerAccountView, AccountNum),true);
            sysTableLookup.addLookupfield(fieldNum(CustomCustomerAccountView, Name));

            queryBuildDataSource = query.addDataSource(tableNum(CustomCustomerAccountView));
            queryBuildDataSource.addSortField(fieldnum(CustomCustomerAccountView,AccountNum));

            sysTableLookup.parmQuery(query);
            sysTableLookup.performFormLookup();
        }
        else if(str2Enum(accountCodeType, formControl.valueStr()) == TableGroupAll::GroupId)
        {
            //lookup that shows the smart atp group id and descriptions
            sysTableLookup = SysTableLookup::newParameters(tableNum(CustomCustomerGroupsView),sender,true);
            sysTableLookup.addLookupfield(fieldNum(CustomCustomerGroupsView, GroupCodeId),true);
            sysTableLookup.addLookupfield(fieldNum(CustomCustomerGroupsView, GroupCodeDescription));

            queryBuildDataSource = query.addDataSource(tableNum(CustomCustomerGroupsView));
            queryBuildDataSource.addSortField(fieldnum(CustomCustomerGroupsView,GroupCodeId));

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

        //cancel super() to prevent error.
        FormControlCancelableSuperEventArgs ce = e as FormControlCancelableSuperEventArgs;
        ce.CancelSuperCall();
    }
 
    /// <summary>
    ///  Selecting the current record from the forms data source
    /// </summary>
    /// <param name="sender">Forms data source as customtablename</param>
    /// <param name="e">Data source event</param>
    [FormDataSourceEventHandler(formDataSourceStr(MyCustomForm, MyCustomRuleTable), FormDataSourceEventType::Activated)]
    public static void MyCustomRuleTable_OnActivated(FormDataSource sender, FormDataSourceEventArgs e)
    {
        FormDataSource formDS = sender.formRun().dataSource(formDataSourceStr(MyCustomForm, MyCustomRuleTable));
        MyCustomRuleTable currentRule = formDS.cursor();
        boolean enableAccountSelection;


        //if the parent code is currently set to all then we should not allow the user to select the child selection field
enableAccountSelection = currentRule.AccountCode == TableGroupAll::All ? false : true;


//apply the allow edit/mandatory logic checks
formDS.object(fieldNum(MyCustomRuleTable, AccountSelection)).allowEdit(enableAccountSelection);
        formDS.object(fieldNum(MyCustomRuleTable, AccountSelection)).mandatory(enableAccountSelection);
     }

    /// <summary>
    /// Account code modified event
    /// </summary>
    /// <param name="sender">MyCustomRuleTable.AccountCode</param>
    /// <param name="e">Event args</param>
    [FormDataFieldEventHandler(formDataFieldStr(MyCustomForm, MyCustomRuleTable, AccountCode), FormDataFieldEventType::Modified)]
    public static void AccountCode_OnModified(FormDataObject sender, FormDataFieldEventArgs e)
    {
        FormDataSource formDS = sender.datasource();
        MyCustomRuleTable currentRule = formDS.cursor();
        boolean enableAccountSelection;

//clear the current account selection anytime the account code is changed
        currentRule.AccountSelection = "";

        //if the parent code is currently set to all then we should not allow the user to select the child selection field
enableAccountSelection = currentRule.AccountCode == TableGroupAll::All ? false : true;

        //apply the allow edit/mandatory logic checks
        formDS.object(fieldNum(MyCustomRuleTable, AccountSelection)).allowEdit(enableAccountSelection);
        formDS.object(fieldNum(MyCustomRuleTable, AccountSelection)).mandatory(enableAccountSelection);
    }
}

No comments:

Post a Comment