Skip to main content

Register Override Trick Used For Form Data Fields Without Overlaying


It is a common customization task to override standard form data source field methods like jumpRef(), modified() or  validate(), lookupReference(), resolveReference() and etc

To achieve this new events were introduced. However on form data source field level we have only 3 available events:

SalesTable

We can try to use form controls instead of form data source fields but this approach has several cons:

  • User can add new control using form personalization and this control won’t support overridden logic. It could be critical if you are restricting field lookup values or adding validations.
  • One form could have several controls that refers to one data source field so you have to duplicate your code.
  • Number of delegates are limited as well. Microsoft will add more later.

For example we want to add custom jumpRef() and validate() methods to itemId field on sales order form. To achieve this we have to either overlay it or use next approach.

First of all we will create class to handle method overrides:

// <summary>
/// Handles events raised by <c>SalesTable</c> form.
/// </summary>
public class SalesTableEventHandler
{
    /// <summary>
    /// Post event handler for <c>SalesTable</c> <c>SalesLine</c> Initialized event.
    /// </summary>
    /// <param name=“_sender”></param>
    /// <param name=“_e”></param>
    [FormDataSourceEventHandler(formDataSourceStr(SalesTable, SalesLine), FormDataSourceEventType::Initialized)]
    public static void SalesLine_OnInitialized(FormDataSource _sender, FormDataSourceEventArgs _e)
    {
        var overrides = SalesTableFormExtensionOverrides::construct();
 
        _sender.object(fieldNum(SalesLine, ItemId)).registerOverrideMethod(methodStr(FormDataObject, jumpRef),
            methodStr(SalesTableFormExtensionOverrides, itemId_OnJumpRef), overrides);
 
        _sender.object(fieldNum(SalesLine, ItemId)).registerOverrideMethod(methodStr(FormDataObject, validate),
            methodStr(SalesTableFormExtensionOverrides, itemId_OnValidate), overrides);
    }
}

Then we will create new event handler class and subscribe to OnInitialized event of SalesLine data source.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/// <summary>
/// Contains methods which are used to override <c>SalesLine</c> data source field methods.
/// </summary>
public class SalesTableFormExtensionOverrides
{
    protected void new()
    {
    }
 
    /// <summary>
    /// Constructs a new instance of <c>SalesTableFormExtensionOverrides</c> class.
    /// </summary>
    /// <returns>
    /// A <c>SalesTableFormExtensionOverrides</c> class.
    /// </returns>
    public static SalesTableFormExtensionOverrides construct()
    {
        return new SalesTableFormExtensionOverrides();
    }
 
    /// <summary>
    /// Provides the open main table functionality for an item.
    /// </summary>
    /// <param name ="_targetField"> The <c>FormDataObject</c> where the jumpRef is triggered.</param>
    public void itemId_OnJumpRef(FormDataObject _targetField)
    {
        InventTable::jumpRefItemId(_targetField.getValue(), OpenMode::Edit);
    }
 
    /// <summary>
    /// Checks whether <c>ItemId</c> is valid.
    /// </summary>
    /// <param name = "_targetField"> The <c>FormDataObject</c> where the Validate is triggered.</param>
    public boolean itemId_OnValidate(FormDataObject _targetField)
    {
        //emulate super() call. Comment out to skip.
        boolean ret = _targetField.validate();
 
        if (ret)
        {
            //custom validation here.
        }
 
        return ret;
    }
}

That’s all. Using this approach you can override any data source field method.

Comments

Popular posts from this blog

Edit Method on Form

Edit Method D365 for a form Data Source 1. To create an edit method first create a controller class. with following properties  public static edit MainAccountNum LedgerJournalTransLedger(LedgerJournalTrans _ledgerjournal, boolean _set, MainAccountNum _id) { MainAccountNum accountId = _id; MainAccount mainAccount = MainAccount::findByMainAccountId(_id); if(_set) { if(_ledgerjournal.AccountType== LedgerJournalACType::Ledger) { mainAccount = MainAccount::findByMainAccountId(accountId); if(_ledgerjournal.LedgerDimension) { DimensionDefault defaultDim = LedgerDimensionFacade::getDefaultDimensionFromLedgerDimension(_ledgerjournal.LedgerDimension); _ledgerjournal.LedgerDimension = LedgerDimensionDefaultingEngine::getLedgerDimensionFromAccountAndDim(mainAccount.RecId, DimensionHierarchy::getAccountStructure(mainAccount.RecId), defaultDim); } else { _ledgerjournal.LedgerDimension = LedgerDimensionDefaultingEngine::getLedgerDimensionFromAccountAndDim(mainAccount.RecId, DimensionHierarchy::getAcc

Security Objects In D365

   PRIVILEGES, DUTIES AND ROLES IN D365 FinOps To add customize security privilege, duty and role you should follow this flow because it is considered as the best practices  Role---> Duty---->Privilege Duty and Privilege would be created at the back end and where as role would be created at front end  1. create privilege from solution explorer in a project  and add new entry point for output, display or action menus to refer in privilege that for which entity we have to give privilege to the user 3. Now Create a duty from solution explorer same as privilege and add this new created privilege to the duty  Now you can refer this duty to the role created on the front end.   HEY HEY HEY !!!! HACK OF THE DAY !!           THE HIGHEST ACCESS LEVEL  FOR ACTION MENU ITEM IS   DELETE     

Deep Links

  DEEP LINKS FOR SALES ORDERS In this blog we will discuss about generating deep links for any form , record or datasource. Deep links are basically termed for generating URL's through code for any specific record in D365. Using Deep links other environments can access D365 records by using this URL generated from it. 1. In below blog I am creating Deep links for sales order header record. 2. To Access these links one should always be added the user in FinOps to access through URL. Step #1 Create and extension class of  URLUtility class  and also add following code snippet to access this class : using Microsoft.Dynamics.AX.Framework.Utilities; using Microsoft.Dynamics.@Client.ServerForm.Contexts; public static str generateRecordUrl(str _menuItemName, MenuItemType _menuItemType, DataSourceName _dataSourceName, Map _indexFieldValuesMap, DataAreaId _dataAreaId = curExt()) {   System.Uri host = SessionContext::Get_Current().Get_RequestUrl();   UrlHelper.UrlGenerator generator = new Url