Maintaining clean and consistent data is essential in model-driven Power Apps. One common challenge is preventing users from creating duplicate records—especially when selecting items like products, assets, or customers.
In this article, we’ll explore three practical techniques using JavaScript and the Power Apps Client API:
- Check for duplicates before saving (with redirect)
- Block the save using
preventDefault()
- Allow creation, then delete or deactivate with a timer
1. Pre-Save Duplicate Check with Redirect
This method checks for duplicates when the form is in Create mode. If a duplicate is found, it alerts the user and redirects them to the existing record—without saving the current one.
Code Example: validateLookupSelection
async function validateLookupSelection(formContext) {
const formType = formContext.ui.getFormType();
if (formType === 1) { // 1 = Create
const item = formContext.getAttribute("lookup_field")?.getValue();
if (item && item.length > 0) {
const itemId = item[0].id.replace(/[{}]/g, "");
try {
const query = `?$filter=_lookup_field_value eq ${itemId}&$select=recordid`;
const results = await Xrm.WebApi.retrieveMultipleRecords("custom_entity", query);
if (results.entities.length > 0) {
const existingRecordId = results.entities[0].recordid;
await Xrm.Navigation.openAlertDialog({
confirmButtonLabel: "OK",
text: "This item already exists.",
title: "Duplicate Detected"
});
// Prevent this field from being submitted
formContext.getAttribute("lookup_field").setSubmitMode("never");
// Redirect to the existing record
Xrm.Utility.openEntityForm("custom_entity", existingRecordId);
return;
}
} catch (error) {
console.error("Error during validation:", error);
}
}
// Optional: show a section if no duplicate is found
formContext.ui.tabs.get("general").sections.get("general").setVisible(true);
}
}
Learn more about setSubmitMode
in the official docs.
Prevent Save with preventDefault()
If you want to completely block the save operation, use the preventDefault()
method inside the form’s onsave event handler.
Code Example:
function onSave(executionContext) {
const formContext = executionContext.getFormContext();
const item = formContext.getAttribute("lookup_field")?.getValue();
if (item && isDuplicate(item)) {
Xrm.Navigation.openAlertDialog({
title: "Duplicate Detected",
text: "This item already exists."
});
executionContext.getEventArgs().preventDefault(); // Stop the save
}
}
Learn more about preventDefault
in Microsoft Docs.
3. Timer-Based Deactivation or Deletion
Sometimes, you may want to allow the record to be created, but then automatically clean it up if it’s a duplicate. This can be done using a timer in JavaScript or with a Power Automate flow.
JavaScript Example:
setTimeout(async () => {
try {
await Xrm.WebApi.deleteRecord("custom_entity", formContext.data.entity.getId());
Xrm.Navigation.openAlertDialog({
title: "Duplicate Removed",
text: "This record was a duplicate and has been deleted."
});
} catch (error) {
console.error("Error deleting record:", error);
}
}, 5000); // Wait 5 seconds
Tip: Instead of deleting, you could also update a status field to mark the record as inactive.