Home / News / Ribbon Enable Rules using Asynchronous processing
21 May 2020

Ribbon Enable Rules using Asynchronous processing

Set ribbon buttons

Sometimes we need to set ribbon buttons in Dynamics 365 CDS enabled or not based on values in other entities or calculated values. This usually requires the use of a Custom Enable Rule that gets a result from a JavaScript function. A JavaScript function is required to retrieve records from a different entity if this is required to determine whether a ribbon should be visible or not.

Since the Dynamics 365 CDS change to the Unified Client Interface, data must be retrieved from the CDS database using asynchronous processing. The creates a complication for the JavaScript method being called by the Enable Rule. The JavaScript method needs to return a Boolean value to the Enable Rule to set the particular ribbon button enabled or not.

Due to the fact that the data retrieve call is asynchronous, we will not able to determine our desired outcome (based on the retrieve result) by the time the JavaScript method returns a value. The callback function of the asynchronous request runs in a separate execution (thread) and does not return back to the Enable Rule.

This can be demonstrated with an example that enables or disables a ribbon button on the Account entity if the account has any contacts.


Problematic code example:

Fortunately, we can call formContext.ui.refreshRibbon(); in the callback method to tell let the Enable Rule to call the JavaScript method again. This gives us the possibility to return a value to the Enable rule after the asynchronous request has executed.

We will need a Boolean variable called buttonProcessing with a scope outside the method that will store the actual value to be returned to the Enable Rule. For safety, this variable can have an initial value of false. This is so that a ribbon button is not enabled while the asynchronous call is awaiting its response.

We will need another Boolean variable called buttonEnabled to indicate whether the asynchronous call is still being processed. This value has an initial value of True. When the JavaScript method is called by the Enable Rule the first time, the asynchronous request is started. Once the asynchronous request completes, this variable will be set to false before refreshRibbon is called.


Corrected code example:

When the JavaScript function is first called, the asynchronous processing has not started yet, as indicated by the buttonProcessing variable having a value of False . We then initiate the asynchronous request that will retrieve the data we need. The method then returns False to the Enable Rule so that the applicable Ribbon button remains disabled.

Once the asynchronous request completes, we set the buttonProcessing variable to False. Now that we have our result from the async data retrieval, we can determine the desired outcome. We set this result into the buttonEnabled variable. We can then call refreshRibbon to get the Enable Rule to call this JavaScript method again. When this JavaScript method executes again, the buttonProcessing variable will be False. Because of this, it will now just return the value in the buttonEnabled variable to the Enable Rule.

This ribbon button is now enabled or not based a value set during an asynchronous callback.

There is a performance consideration that we should take into account when calling refreshRibbon. All buttons in the form ribbon will be refreshed, so this may have an impact if a lot of buttons have been added to form.  Fortunately, if the above pattern is followed, the logic behind each custom Enable Rule will be executed only once per form load.

To read more about the refreshRibbon method, please see https://docs.microsoft.com/en-us/powerapps/developer/model-driven-apps/clientapi/reference/formcontext-ui/refreshribbon