So I am trying to execute a piece of code on preStageChange event of a Business Process Flow.
For that, I tried to get the workflow ID using the WebAPI, then get the stages of the workflow. If I would manage to do that, I could write a simple if statement to see if I am on the desired stage.
I tried this:
function preStageOnChange(executionContext) {
var formContext = executionContext.getFormContext();
var activeStage = formContext.data.process.getActiveStage();
var stages = null;
Xrm.WebApi.retrieveMultipleRecords("workflow", "?$filter=name eq 'Customer Onboarding'&$select=uniquename&$top=1").then(
function success(result) {
var workflowId = result.entities[0]["workflowid"];
Xrm.WebApi.retrieveMultipleRecords("processstage", "?$select=stagename&$filter=processid/workflowid eq " + workflowId).then(
function success(result) {
stages = result.entities;
},
function (error) {
console.log(error.message);
}
);
},
function (error) {
console.log(error.message)
}
);
var socioeconomicStatus = stages.find(stage => stage["stagename"] == "Socioeconomic Status");
if(activeStage.getId().toString() == socioeconomicStatus["processstageid"]){
if (formContext.getAttribute("ava_netincome").getValue() == null && formContext.getAttribute("ava_investmentincome").getValue() == null && formContext.getAttribute("ava_otherincome").getValue() == null) {
formContext.ui.setFormNotification("At least one income value must be populated", "ERROR", "income_error"); //sets form notification in top of the form
executionContext.getEventArgs().preventDefault(); //prevent navigation to next stage
}
else {
formContext.ui.clearFormNotification("income_error");
}
if (formContext.getAttribute("ava_householdexpenses").getValue() == null && formContext.getAttribute("ava_otherexpenses").getValue() == null) {
formContext.ui.setFormNotification("At least one expense value must be populated", "ERROR", "expense_error"); //sets form notification in top of the form
executionContext.getEventArgs().preventDefault(); //prevent navigation to next stage
}
else {
formContext.ui.clearFormNotification("expense_error");
}
if (formContext.getAttribute("ava_currentloan").getValue() != null && formContext.getAttribute("ava_loanexpenses").getValue() == null)
{
formContext.ui.setFormNotification("Loan expenses must be populated", "ERROR", "loan_error"); //sets form notification in top of the form
executionContext.getEventArgs().preventDefault(); //prevent navigation to next stage
}
else {
formContext.ui.clearFormNotification("loan_error");
}
}
}
Basically I am trying to execute the code when I am on the "Socioeconomic Status" stage, before going to the next stage. The reason I'm trying to do this is because I want to prevent the user from going to the next stage if they made any errors while filling out the form.
I realize that the WebAPI call I am using is async, so I tried awaiting it, making the event handler function async, but it doesn't seem to work that way either.
Another thing I tried is placing the error handling code into the success function of the WebAPI call, but if I do that I can't access the outer event so executionContext.getEventArgs().preventDefault();
stops working.
How can I make my error handling code run on a specific stage so that I can still prevent the user from going to the next stage?
Xrm.WebApi.retrieveMultipleRecords
is a function that is executed asynchronously. It returns a Promise that is intended to chain subsequent asynchronous handlers.
A call to this promise function returns control to the thread before its asynchronous code is executed. Therefore the line var socioeconomicStatus = stages.find()
is executed before stages
is set properly.
Once in a promise chain you have to go through it to the end like this:
Xrm.WebApi.retrieveMultipleRecords("workflow", "?$filter=name eq 'Customer Onboarding'&$select=uniquename&$top=1")
.then(result => {
const workflowId = result.entities[0]["workflowid"];
return Xrm.WebApi.retrieveMultipleRecords("processstage", "?$select=stagename&$filter=processid/workflowid eq " + workflowId);
})
.then(result => {
var socioeconomicStatus = result.entities.find(stage => stage["stagename"] == "Socioeconomic Status");
if (activeStage.getId().toString() == socioeconomicStatus["processstageid"]) {
if (formContext.getAttribute("ava_netincome").getValue() == null && formContext.getAttribute("ava_investmentincome").getValue() == null && formContext.getAttribute("ava_otherincome").getValue() == null) {
formContext.ui.setFormNotification("At least one income value must be populated", "ERROR", "income_error"); //sets form notification in top of the form
executionContext.getEventArgs().preventDefault(); //prevent navigation to next stage
}
else {
formContext.ui.clearFormNotification("income_error");
}
if (formContext.getAttribute("ava_householdexpenses").getValue() == null && formContext.getAttribute("ava_otherexpenses").getValue() == null) {
formContext.ui.setFormNotification("At least one expense value must be populated", "ERROR", "expense_error"); //sets form notification in top of the form
executionContext.getEventArgs().preventDefault(); //prevent navigation to next stage
}
else {
formContext.ui.clearFormNotification("expense_error");
}
if (formContext.getAttribute("ava_currentloan").getValue() != null && formContext.getAttribute("ava_loanexpenses").getValue() == null) {
formContext.ui.setFormNotification("Loan expenses must be populated", "ERROR", "loan_error"); //sets form notification in top of the form
executionContext.getEventArgs().preventDefault(); //prevent navigation to next stage
}
else {
formContext.ui.clearFormNotification("loan_error");
}
}
})
.catch(error => {
console.log(error.message);
});
As you can see, there is only one error handler. When the first query fails, it automatically skips the .then
functions and proceeds with the .catch
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.