Business Applications, dynamics 365, Model-driven, PowerApps, Uncategorized

Dynamics 365 CE/model-driven app: the form script unexpected discovery

Something I won’t expect to discover. Yet, here I am!

It’s all started with a very “simple” requirement to populate a read-only form field on change of another form field, Method. The fancy way it set up is when you select the field to change it pops up the window asking you if it was a client decision or not to change the field. If you answer Yes it sets the MethodSetBy field to a “Client” otherwise it sets it to “Vendor” or something.

Easy!

My function, ClientMethodChange, looked like this (with a much less ugly formatting):

var confirmStrings = { text: "Is this change due to a client request?", title: "Confirmation Dialog", cancelButtonLabel: "No", confirmButtonLabel: "Yes" };
var confirmOptions = { height: 200, width: 450 };

Xrm.Navigation.openConfirmDialog(confirmStrings, confirmOptions).then(
function (success) {
          if (success.confirmed) {
 //set to Client
                                        formContext.getAttribute("methodsetby").setValue(MethodSetBy.Client);
}
         else {
 //set to Vendor                    formContext.getAttribute("methodsetby").setValue(MethodSetBy.Vendor);
                }

         
 });

During the testing it was discovered that if a person changes the method field then navigates to another form the MethodSetBy field loses the change. (Obviously!)

To solve “the problem” we decided to use a force save statement in the JavaScript.

formContext.data.entity.save();

For some reason it wasn’t fully working still. So … I went debugging. I this is what I discovered.

I called my ClientMethodChange function from another function and performed the force save in the parent function.

this.MethodChange = function (executionContext) {
var formContext = executionContext.getFormContext();

var accountType = formContext.data.entity.attributes.getByName("zzz_accounttype");
var accountTypeValue = accountType.getValue();
if (accountTypeValue == AccountType.Client) {
<my_namepspace>.ClientMethodChange(formContext);
}
else {
if (accountTypeValue == AccountType.Property) {
<my_namepspace>.PropertyMethodChange(formContext);
}
}
var currentDateTime = new Date();
formContext.getAttribute("zzz_lastenmethodchange").setValue(currentDateTime);
formContext.data.entity.save();
}

Because I was expecting that my function will be called from the parent and all steps will be performed synchronously. I expected the parent function to wait until the child function finished its steps. Silly me!

The debugging relieved that after calling the ClientMethodChange function the parent function continued with its the steps.

In my case the force save was performed prior the MethodSetBy was set in the child function. The change wasn’t saved.

Summary: read carefully, please. I tested it on the brand new environment for a model-driven app. If you call one form function within another function the child function steps will be performed asynchronously in relation to the parent function. Whatever you do after the child function is called, the parent function will not wait for the completion of the child function. Thanks to Alex Shlega I don’t feel like a crazy person anymore! The mysterious “async” effect was triggered by Xrm.Navigation.openConfirmDialog which was delaying the update of the field (due of its truly async nature).

Our life is full of dramatic discoveries. One of those made my Friday amazing and “ain’t boring”.

Also, shouting out to my partner who said that it’s not possible and there is something more to it! Yes, you were right. (I really said it)

Happy coding!

1 thought on “Dynamics 365 CE/model-driven app: the form script unexpected discovery”

Leave a comment