Wednesday, May 17, 2017

D3FO: Customizing interaction classes using extensions

Dynamics AX technical community is finding cool and tricky ways to create extensions for customization's. In this post, let’s do a quick walk through on how we can customize a list page interaction class via extensions.  
To do this let's add a new button on sales order list page and enable/disable it on the basis of sales order status.

Below are the high level steps :
  • Create a new class to write the business logic to be executed by your new button.
  • Create a new menu item linked to your class
  • Create extension of the list page and add your new button
  • Create event handler for the list page interaction class and enable/disable the new button 

Let's create a new class: I have shown the total sales order amount in the Info-log, to show an example of business process in the method.

Now we create a new action type menu item for this class as shown below:

Create an extension of SalesTableListPage from : To do this, right click on the SalesTableListPage object in the AOT  and select "Create extension" . Make sure your model, where you are creating the project, has a reference to Application suite else this option will not be enabled.

In the designer window, expand the design node and navigate to the action pane where you want to add the button. Let’s add a new button group and add the menu item we created

Verify that the menu item button is having correct properties and define the data source property as SalesTable

Build the project and test the button. When you open the sales table list page the new button is visible

Click on the button just to make sure that it’s working. On clicking it we can see that Infolog is shown to display the Sales order total amount

Now let's add more logic to our button to only be enabled for sales orders which are not invoiced. Typically we would go to the interaction class and modify the function which is enabling/disabling button, but we want to do this without customizing the standard class and with the use of extensions.
That means we need to subscribe to the method of the interaction class. We can see that interaction class as methods available which are pretty much self-explanatory by their names. We can see there are few methods which set the button properties 

As we added the button in the sales order action pane group we can see that there is a method in this class which used to set buttons on the sales order action pane tab menu items . Notice that this is a protected method.  

Ideally you may want to create an event handler for this method. Try to right click on this method and then select the option to create a post event handler 

You will be greeted with the below error message. We can only create event handlers for Hookable methods. The definition of  Hookable method is also shown in the error message, these are non-abstract methods that are either public or tagged with the "Hookable" attribute as true. 

Let's find a hookable method in the interaction class:  On a quick scan in the class you can see that the setButtonEnabled() method is a protected method and decorated with the "HookableAttribute" as true. 

This is an important point for ISV's to consider when design their solutions, as this attribute will be helpful to tag extension plugs.Let's create an event handler listener for this method 

Add the event handler in the new class which we already created 

Now we need to  :
·         Get the object of the interaction class
·         Get the current sales table record
·         Set the button access

The below lines of code represent each step 

Below is the code text in case you want to reuse it
    /// This method enables/disables the new process button based on the sales order status

    [PostHandlerFor(classStr(SalesTableListPageInteraction), methodStr(SalesTableListPageInteraction, setButtonEnabled))]
    public static void SalesTableListPageInteraction_Post_setButtonEnabled(XppPrePostArgs args)
        SalesTableListPageInteraction salesTableListPageInteraction = args.getThis();
        SalesTable salesTable = salesTableListPageInteraction.listPage().activeRecord(queryDataSourceStr(SalesTableListPage, SalesTable)) as SalesTable;
        salesTableListPageInteraction.listPage().actionPaneControlEnabled(formControlStr(SalesTableListPage, RGSalesProcess),SalesTable.SalesStatus != SalesStatus::Invoiced);

Now we build the project and run the list page form to see if the button is disabled for invoiced sales orders:
The button is disabled for an invoiced sales order

The button is enabled for a sales order having a status other than Invoiced.

Thanks for reading the blog. Your feedback is welcome and keep sharing any cool ideas around extensions and the new frameworks of D3FO. 

1 comment: