Use Client Script to stop Next stage and Previous stage movement in Dynamics 365/ CDS Business Process Flows–Use the addOnPreStageChange event.

Follow my blog for more interesting topics on Dynamics 365, Portals and Power Platform. For training and consulting, write to us at info@xrmforyou.com

This one is another requirement which comes across every now. And while it seems quite easy to do, it actually is not.


This is because of the limitation of Client API in Dynamics 365. Since the time Business Process flows have been introduced in Dynamics 365, there exists an event in WebAPI – “OnStageChange”. However there is a perennial problem with this event. While you can register your event handlers for this event and control the stage movement, the event fires after the stage movement has already happened. So basically if a user clicks on Next stage button, the event will fire once the user have moved to the next stage and then you need to move back the stage again if required depending on business conditions.


Well the wait is finally over. Microsoft have finally introduced the event – “onPreStageChange”. This event actually fire before the stage movement happen.
Below is the sample code on how you can stop the Next and Previous stage movement in JavaScript.

var Acc = {};
Acc.formEvents = {
    form_load: function (e) {
       var fc = e.getFormContext();
       // use the below code to remove a registered event handler.
       //fc.data.process.removeOnPreStageChange(Acc.formEvents.handlePreStage);
       fc.data.process.addOnPreStageChange(Acc.formEvents.handlePreStage);
    },
    handlePreStage: function (e) {
       debugger;
       // get the event arguments
       var bpfArgs = e.getEventArgs();


      if (bpfArgs.getDirection() === "Previous") // back stage movement is not allowed; You can stop it depending on custom business logic as well
       {
          bpfArgs.preventDefault();
          var alertStrings = { confirmButtonLabel: "OK", text: "Back stage movement is not allowed", title: "Sample title" };
          var alertOptions = { height: 120, width: 260 };
          Xrm.Navigation.openAlertDialog(alertStrings, alertOptions);
          return;
       }


      if (bpfArgs.getDirection() === "Next") { // only next stage movement is allowed. You can stop it depending on custom business logic as well
          // stop the stage movement
          bpfArgs.preventDefault();
          alertStrings = { confirmButtonLabel: "OK", text: "Next stage movement is not allowed", title: "Sample title" };
          alertOptions = { height: 120, width: 260 };
          Xrm.Navigation.openAlertDialog(alertStrings, alertOptions);
          return;
       }
       // you can also play with the other properties of eventargs
       // get the stage - bpfArgs.getStage();
       // get the steps - bpfArgs.getStage().getSteps();
    }
};

As you can see, I have registered a function on pre-stage event. And then inside the event I am stopping the Next and Previous stage movement. You can observe how I am determining the Next or Previous button click.

You can also explore the other values inside the eventArgument. I have mentioned it in comments.

Hope this helps!
Debajit Dutta
(Microsoft MVP)