You're right, the behavior you're experiencing (staying on the same page or asking to save again) likely occurs because the Xrm.navigate.openForm() is being called before the save operation initiated by ExecutionContext.data.entity.save() has actually completed. The save() method is asynchronous.
Here's how you can correctly incorporate getIsDirty() and ensure the form is saved before navigating, along with copying values to the new form:
function onButtonClick(executionContext) {
var formContext = executionContext.getFormContext();
// Check if the form has unsaved changes
if (formContext.data.entity.getIsDirty()) {
// Save the form and then navigate
formContext.data.entity.save().then(
function successCallback(saveResult) {
// Form saved successfully, now navigate and pass values
var abcid = formContext.data.entity.getId();
var xyz = formContext.getAttribute("crm-xyz").getValue();
var formParameters = {};
if (abcid) {
formParameters["relatedRecordId"] = abcid; // Example: Passing the current record ID
formParameters["relatedRecordType"] = formContext.data.entity.getEntityName(); // Example: Passing the current entity logical name
}
if (xyz) {
formParameters["new_xyzField"] = xyz; // Example: Passing the value of 'crm-xyz' to a field in the new form
}
var options = {
entityLogicalName: "your_new_entity_logical_name", // Replace with the logical name of the entity for the new form
// Optional: Specify form parameters to pre-populate fields in the new form
parameters: formParameters
};
Xrm.Navigation.openForm(options);
},
function errorCallback(error) {
console.log("Error during save: " + error.message);
// Optionally display an error message to the user
}
);
} else {
// Form is not dirty, navigate immediately
var abcid = formContext.data.entity.getId();
var xyz = formContext.getAttribute("crm-xyz").getValue();
var formParameters = {};
if (abcid) {
formParameters["relatedRecordId"] = abcid;
formParameters["relatedRecordType"] = formContext.data.entity.getEntityName();
}
if (xyz) {
formParameters["new_xyzField"] = xyz;
}
var options = {
entityLogicalName: "your_new_entity_logical_name", // Replace with the logical name of the entity for the new form
parameters: formParameters
};
Xrm.Navigation.openForm(options);
}
}
Explanation of Changes:
formContext: We get the formContext object, which is the recommended way to interact with the form in modern Dynamics 365.
formContext.data.entity.getIsDirty(): This method checks if there are any unsaved changes on the current form.
- Conditional Save:
- If
getIsDirty() is true:
- We call
formContext.data.entity.save(). This returns a Promise.
- We use
.then() to execute code after the save operation has completed successfully.
successCallback: Inside this function, we get the abcid and xyz values and then use Xrm.Navigation.openForm() to open the new form.
- Passing Values: We use the
parameters option of Xrm.Navigation.openForm() to pass values to the new form.
relatedRecordId: An example of passing the ID of the current record.
relatedRecordType: An example of passing the logical name of the current entity.
new_xyzField: Replace "new_xyzField" with the actual schema name of the field in your new form where you want to copy the value of xyz.
- We also include an
.catch() (or the second argument to .then(), errorCallback) to handle potential errors during the save operation.
- If
getIsDirty() is false:
- We directly proceed to get the values and open the new form using
Xrm.Navigation.openForm().
Important Considerations:
Xrm.Navigation.openForm(): Make sure you are using Xrm.Navigation.openForm() (with a capital 'N') for modern Dynamics 365 development. Xrm.navigate.openForm() is the older syntax.
your_new_entity_logical_name: Replace this placeholder with the actual logical name of the entity for the form you want to open. You can find this in the entity customization settings.
new_xyzField: Crucially, replace "new_xyzField" with the correct schema name of the field in the new form where you want to copy the value of xyz.
- Error Handling: The
errorCallback in the save().then() should include appropriate error logging or user feedback to handle cases where the save operation fails.
- Asynchronous Nature: Remember that
save() is asynchronous. The .then() block ensures that the navigation and value passing happen only after the save is successful.
By implementing this approach, you ensure that the current form's details are saved (if there were changes) before the new form is opened, preventing the issues you were encountering. You also correctly pass the desired values to the new form using the parameters option of Xrm.Navigation.openForm().