I have the below code that checks two things on the Field Service Bookable Resource Booking Form which is a combination of two forms which is why I have to do a web API call and also works in Offline mode.
This is a continuation of this post in Field Service however I feel it's more generic javascript issue now.
The code is from Andrew Butenko in this post which I modified slightly.
The code basically checks OnSave:
- If booking status is complete
- If Incident Type is Breakdown check Fault Category not Null
- All Service Tasks are complete
It all works except when I try to Save a Booking with Incident Type Breakdown and Fault Category is not null, it just gets an infinite loop.
In the debugger it runs through hits this:
- isValidationNeeded = false;
It then re-enters the OnSave function and exits when it hits
- if (!isValidationNeeded) {
isValidationNeeded = true;
return;
}
It is then when it just seems to loop through this section.
I expected that as executionContext.getEventArgs().preventDefault(); is further down it should just exit and Save.
When it is the service Tasks and WO is not Incident Type Breakdown it works perfectly and gracefully exits.
Could the new Async Save setting be effecting this?
var BookingForm = (function () {
var SaveMode = {
Save: 1,
SaveAndClose: 2,
SaveAndNew: 59,
Autosave: 70
};
//this is variable that shows if validation was successfully passed or not
var isValidationNeeded = true;
function OnSave(executionContext) {
//so if there are several save handlers and one of previous already called preventDefault
//there is no need to do any validations anymore
if (executionContext.getEventArgs().isDefaultPrevented()) {
return;
}
//getting save mode from event
var saveMode = executionContext.getEventArgs().getSaveMode();
//if savemode is not one of listed - just quit the execution and let the record to be saved
if (saveMode !== SaveMode.Save &&
saveMode !== SaveMode.SaveAndClose &&
saveMode !== SaveMode.SaveAndNew &&
saveMode !== SaveMode.Autosave) {
return;
}
//so if validation was successfully passed - flag is reset
//and code just leaves the form alone and allows changes to be saved
if (!isValidationNeeded) {
isValidationNeeded = true;
return;
}
//getting of the form context from execution context object
var formContext = executionContext.getFormContext();
// Get WO Guid
var wo = formContext.getAttribute('msdyn_workorder').getValue()[0].id; // returns GUID
// Fetch will return any service tasks that are incomplete and related to WO. Using FetchXml allows us to use same querey in online and offline mode
let fetchXml = "?fetchXml=";
var tasks = 0;
if (formContext.getAttribute("bookingstatus") != null && formContext.getAttribute("bookingstatus") != undefined)
{
var status = formContext.getAttribute("bookingstatus").getValue()[0].name;
if(status == "Completed")
{
var faultcategory = formContext.ui.tabs.get(3).sections.get(0).controls.get(0).getAttribute("eye_faultcategory").getValue();
var incidenttype = formContext.ui.tabs.get(3).sections.get(0).controls.get(0).getAttribute("msdyn_primaryincidenttype").getValue()[0].name;
var workordertype = formContext.ui.tabs.get(3).sections.get(0).controls.get(0).getAttribute("msdyn_workordertype").getValue()[0].name;
if (status == "Completed" && (incidenttype == "Breakdown" || incidenttype == "Trapped Passenger" || incidenttype == "Repairs") && faultcategory == null) {
// executionContext.getEventArgs().preventDefault(); // Stop the Save
formContext.ui.tabs.get(3).sections.get(0).controls.get(0).getAttribute("eye_faultcategory").setRequiredLevel("required");
}
//preventing of the save operation before async operation is started
executionContext.getEventArgs().preventDefault();
Xrm.WebApi.retrieveMultipleRecords("msdyn_workorderservicetask", fetchXml).then(
function success(results) {
tasks = results.entities.length;
if(results.entities.length !== 0)
{
console.log(`In retrieve call ${tasks}`);
formContext.ui.setFormNotification("All WO service tasks need to be complete", "ERROR", "DurationErrorMessageId");
}
else
{
//othervice validation flag is set to "Passed"
isValidationNeeded = false;
//and save event is called again and notification cleared
formContext.ui.clearFormNotification("DurationErrorMessageId");
if (saveMode === SaveMode.Save || saveMode === SaveMode.Autosave) {
formContext.data.entity.save();
} else if (saveMode === SaveMode.SaveAndClose) {
formContext.data.entity.save("saveandclose");
} else {
formContext.data.entity.save("saveandnew");
}
}
},
function (error) {
//if something went wrong - error message is shown to user
Xrm.Navigation.openAlertDialog({ text: error.message });
}
);
} else {
// Booking status not complete so clear notifications and allow save
formContext.ui.clearFormNotification("DurationErrorMessageId");
return;
}
}
}
return {
OnSave: OnSave
};
} // BookingForm Function
) // BookingForm
();