AX 7. Display methods and Form Observability.

In AX 2012 display methods are called every time when a form is redrawn, however this behaviour is changed in AX 7 to optimize performance in web client.

Using Form Observability, we can notify form that display method should be updated or recalculated when related variable, data source or control are updated.

There are three different scenarios:

  • Display method depends on a variable.
  • Display method depends on another data source.
  • Display method depends on an event.

Display method depends on a variable.

For example, we have a form level variable “valid, display method that shows a status on the form and button to update the status.

MyForm

[Form]
public class MyForm extends FormRun
{
    [FormObservable]
    boolean valid;

    display public boolean displayIsValid()
    {
        return valid;
    }

    [Control("Button")]
    class Validate
    {
        public void clicked()
        {
            super();
            valid = true;
        }
    }
}

When the form is opened display method will be executed and show default value (false) on the form. When the button is clicked AX does not execute display method so value on the form remains the same.

However variable is decorated with FormObservable attribute and AX will observe it and automatically execute display method when value of the variable is changed.

Form can observe form level variables and class level variables as well. For example, AssetChangeGroup class has couple of variables decorated with FormObservable attribute.

class AssetChangeGroup extends RunBase
{
    [FormObservable]
    AssetGroupId        assetGroupId;

    [FormObservable]
    NoYesId             changeAssetId;

    [FormObservable]
    AssetId             assetId;
}

This class is used in edit methods of AssetChangeGroup form.

[Form]
public class AssetChangeGroup extends FormRun
{
    edit AssetGroupId assetGroupId(boolean set, AssetGroupId _assetGroupId)
    {
        if (set)
        {
            assetChangeGroup.parmAssetGroupId(_assetGroupId);
            element.initAssetId();
            element.enableOrDisableAssetId();
        }

        return assetChangeGroup.parmAssetGroupId();
    }

So any update of class level variables will trigger update of edit methods on the form.

Display method depends on another data source.

In the next example we have a simple header-lines form.

HeaderLine

There is a display method on the header grid that shows total lines quantity.

[Form]
public class MyForm extends FormRun
{
    [DataSource]
    class MyHeader
    {
        public display Qty displayTotal(MyHeader _myHeader)
        {
            MyLine_DS.observe();
            MyLine  myLineLocal;

            select sum(Qty) from myLineLocal
                where myLineLocal.MyHeader == _myHeader.RecId;

            return myLineLocal.Qty;
        }
    }
}

Here MyLine_DS.observe() is used to observe MyLine_DS data source. AX will automatically execute display method if any record in the lines grid is updated, inserted or deleted.

Display method depends on an event.

In some cases, display method does not depend on a forms state or a data source. However, it should be refreshed on a specific event, like a button click or a method call. To handle this, we can use FormObservableLink object.

In the next example we have a form with a display method and a button that invokes a class method. This method will update  data that the display method depends on and invoke  the method on the form to notify the display method that it should be updated.

UpdateLines

Class does records update and calls a method on the form:

class MyClass
{
    public static void main(Args _args)
    {
        MyHeader myHeader = _args.record() as MyHeader;

        if (myHeader)
        {
            MyLine myLine; 

            ttsbegin;
            update_recordset myLine
            setting Qty = 10
                where myLine.MyHeader == myHeader.RecId;
            ttscommit;

            var caller = _args.caller();

            if (caller && Global::formHasMethod(caller, formMethodStr(MyForm, refreshTotals)))
            {
                caller.refreshTotals();
            }
        }
    }
}

On the form linesTotalObservableLink.markChanged() is used to notify the form that it should execute the display method and linesTotalObservableLink.observe() to receive notification.

[Form]
public class MyForm extends FormRun
{
    FormObservableLink linesTotalObservableLink;

    public void refreshTotals()
    {
        linesTotalObservableLink.markChanged();
    }

    public void init()
    {
        super();
        linesTotalObservableLink = new FormObservableLink();
    }

    [DataSource]
    class MyHeader
    {
        public display Qty displayTotal(MyHeader _myHeader)
        {
            linesTotalObservableLink.observe();

            MyLine  myLineLocal;

            select sum(Qty) from myLineLocal
                where myLineLocal.MyHeader == _myHeader.RecId;

            return myLineLocal.Qty;
        }
    }
}
Advertisements