Create multiselect dialog field

How can I make the dialog field support multiselection ?

I have this code in X++ and i want to add a multitselect field in dialog for journalnameid and filter the query based on this result from dialog

[Form]
public class TTAssetMovementForm extends FormRun
{
///


///
///

///
///

public str getDimensionDisplayValue(RecId defaultDimension, Name dimName)
{
    DimensionAttributeValueSetStorage dimStorage;
    dimStorage = DimensionAttributeValueSetStorage::find(defaultDimension);
    return dimStorage.getDisplayValueByDimensionAttribute(DimensionAttribute::findByName(dimName).RecId);
}


public void init()
{   
    super();
    
    date startDate;
    date endDate;

    InventJournalTable inventJournalTable;
    InventJournalTrans inventJournalTrans;
    InventDim inventDim;
    AssetMovement reportTmp;

    DimensionAttributeValueSet dimensionAttributeValueSet;
    DimensionAttributeValueSetItem dimensionAttributeValueSetItem;
    DimensionAttributeValue    dimensionAttributeValue;
    DimensionAttribute         dimensionAttribute;

    DialogField dialogList;
    container listValues;
    str selectedValue;


   

    Dialog dialog;
    DialogField dfStartDate, dfEndDate;
    boolean dialogResult;

    dialog = new Dialog('Asset Movement Filter Dialog');

    
    dfStartDate = dialog.addField(extendedTypeStr(DocumentDate), 'Start Date');
    dfEndDate = dialog.addField(extendedTypeStr(DocumentDate), 'End Date');
    dialogList = dialog.addField(EnumStr(InventJournalType));
    dialogResult = dialog.run();
    if (dialogResult)
    {
        
        startDate = dfStartDate.value();
        endDate = dfEndDate.value();
        selectedValue = dialogList.value();
        
        if (!startDate || !endDate || !selectedValue)
        {
            error("Please enter valid Filters.");
            return;
        }

        delete_from reportTmp;
        // Perform the while select with joins
        while select * from inventJournalTrans
           Where  inventJournalTrans.JournalType == str2Int(selectedValue) &&
            inventJournalTrans.TransDate >= startDate && inventJournalTrans.TransDate <= endDate
         join inventJournalTable
            where inventJournalTable.JournalId == inventJournalTrans.JournalId &&
                  inventJournalTable.DATAAREAID == inventJournalTrans.DATAAREAID 
         join inventDim
            where inventJournalTrans.InventDimId == inventDim.InventDimId &&
                  inventJournalTrans.DATAAREAID == inventDim.DATAAREAID
        
        {
            // Populate the temporary table with data
            /* while select * from   dimensionAttributeValueSet  
                where inventJournalTrans.DefaultDimension == dimensionAttributeValueSet.RecId
                JOIN dimensionAttributeValueSetItem where dimensionAttributeValueSetItem.DimensionAttributeValueSet == dimensionAttributeValueSet.RecId
                JOIN dimensionAttributeValue  where dimensionAttributeValue.RecId == dimensionAttributeValueSetItem.DimensionAttributeValue
                JOIN dimensionAttribute where dimensionAttribute.RecId == dimensionAttributeValue.DimensionAttribute 
            {
                if (dimensionAttribute.DimensionKeyColumnName == "BRANCHESTG") {
                        reportTmp.BranchesTG = str2Int(dimensionAttributeValueSetItem.DisplayValue);
                }
                if (dimensionAttribute.DimensionKeyColumnName == "CONSTRUCTIONTG")
                {
                    reportTmp.ConstructionTG = str2Int(dimensionAttributeValueSetItem.DisplayValue);
                }

            }*/ 

            reportTmp.BranchesTG = str2Int(this.getDimensionDisplayValue(inventJournalTrans.DefaultDimension, 'BranchesTG'));
            reportTmp.ConstructionTG = str2Int(this.getDimensionDisplayValue(inventJournalTrans.DefaultDimension, 'ConstructionTG'));

            reportTmp.TransDate = inventJournalTrans.TransDate;
            reportTmp.JournalId = inventJournalTable.JournalId;
            reportTmp.Voucher = inventJournalTrans.Voucher;
            reportTmp.JournalNameId = inventJournalTable.JournalNameId;
            reportTmp.Description = inventJournalTable.Description;
            reportTmp.ItemId = inventJournalTrans.ItemId;
            reportTmp.Posted = inventJournalTable.Posted;
            reportTmp.WorkflowApprovalStatus = inventJournalTable.WorkflowApprovalStatus;
            reportTmp.InventSiteId = inventDim.InventSiteId;
            reportTmp.InventLocationId = inventDim.InventLocationId;
            reportTmp.OffsetAccount = inventJournalTrans.ledgerDimensionDisplayValue();
            reportTmp.Qty = inventJournalTrans.Qty;
            reportTmp.CostPrice = inventJournalTrans.CostPrice;
            reportTmp.CostAmount = inventJournalTrans.CostAmount;

          
            // Insert the record into the temporary table
            reportTmp.insert();
        }

        FormDataSource dataSource = this.dataSource('AssetMovement');


        if (dataSource)
        {
            dataSource.executeQuery();
        }


    } 
}

}

‘’’

Don’t you rather want to use a query and allow users to set query ranges? For example:

It gives users much more flexibility (which is usually a good thing, but not always).

By the way, there is no need to manually add join conditions on DataAreaId (such as inventJournalTable.DATAAREAID == inventJournalTrans.DATAAREAID). It’s done automatically by F&O kernel.

Don’t use application names hard-coded as text, such as in this.dataSource('AssetMovement'). And there is even an easier way to get the data source: it’s already in assetMovement_ds variable (assuming that your form does have a data source called AssetMovement.

1 Like

How can I modify the code to do the method that you have said ?

There are several possible approaches.

For example:

  • Use SysOperation framework with a query in the report contract. The whole dialog form will be generated for you. You’ll just need to be careful with getting the temporary buffer to your form. For sure, use synchronous execution mode.
  • Use QueryRun.prompt(). For example, look at promptVoucher() method in TaxTrans form.

As always, you need to consider your business requirements when designing the technical solution, because the whole purpose of the implementation is addressing a business problem.

Sorry but I am newbie in Dynamics 365 so I don’t know how to do it ?

Then I suggest you consider the other approach (with QueryRun.prompt()), because it’s simpler. (Nevertheless I can’t say whether it meets requirements of your users/client). Look at the example in the standard form.

But you’ll need to learn about SysOperation framework as well; it’s very important. For example, dialogs aren’t usually created by Dialog class directly; you typically let the SysOperation framework generate a dialog for you. You also need this framework for batch processing, reports etc. Fortunately, you can find a plenty of information on internet, e.g. this tutorial on SysOperation framework.