4

I'm using lightning:recordEditForm on the Account object which also has duplicate rules set up. If I attempt to create a duplicate record via this form lightning:messages simply displays the following error:

You're creating a duplicate record. We recommend you use an existing record instead.

Whereas if I attempt to create a duplicate through the standard UI it provides a link which open a new modal showing the duplicate records and allowing the user to select one. Is there a straightforward way to replicate this or do I need to roll my own?

example code:

<aura:component>
<lightning:recordEditForm aura:id="recordEditForm" objectApiName="Contact">
    <lightning:messages />
    <lightning:inputField fieldName="Name" />
    <lightning:button class="slds-m-top_small" type="submit" label="Create new" />
</lightning:recordEditForm>

4
+50

In my experience you have to build your own error handler and iterate through the results of the error message

So on the form, you add an onerror handler

<lightning:recordEditForm 
                          aura:id="recordEditForm" 
                          objectApiName="Contact"
                          onerror="{!c.handleError}"
                          >

And in the controller, you'd add something like this:

({
    handleError : function(component, event, helper) {

        component.set("v.showSpinner", false);
        var message = '';
        var errors = event.getParams();
        console.log(errors);
        var errormessages = errors.output;

        if ($A.util.isEmpty(errormessages.errors) === false) {
            if (errormessages.errors.length > 0) {
                for (var j = 0; errormessages.errors.length > j; j++) {
                    var fielderror = errormessages.errors[j];
                    if (fielderror.errorCode === 'DUPLICATES_DETECTED') {
                        message += 'Looks like this might be a duplicate. Click on the “Return to Search” button to find this contact';
                    }
                    else {
                        message += fielderror.errorCode + ' (' + fielderror.field + ') : ' + fielderror.message;
                    }
                }
            }
        }

        var toastEvent = $A.get("e.force:showToast");
        toastEvent.setParams({
            "type": "error",
            "title": "Error on Save!",
            "message": message
        });
        toastEvent.fire();
    }
})

The error object will return something like this for Duplicate Matches, so you can iterate through the results and post something to the message and/or a toast

{
  "message": "An error occurred while trying to update the record. Please try again.",
  "detail": "Use one of these records?",
  "output": {
    "errors": [
      {
        "constituentField": null,
        "duplicateRecordError": {
          "matchResults": [
            {
              "apiName": "Contact",
              "isAllowSave": true,
              "matchRecordIds": [
                "003f400000gtfc2AAA"
              ],
              "matchRule": "Standard_Contact_Match_Rule_v1_1",
              "objectLabel": "Contact",
              "objectLabelPlural": "Contacts",
              "themeInfo": {
                "color": "A094ED",
                "iconUrl": "https://lexpictures-dev-ed.my.salesforce.com/img/icon/t4v35/standard/contact_120.png"
              }
            }
          ]
        },
        "errorCode": "DUPLICATES_DETECTED",
        "field": null,
        "fieldLabel": null,
        "message": "Use one of these records?"
      }
    ],
    "fieldErrors": {

    }
  },
  "error": {

  }
}
  • This is what we do. The problem is that even the non-blocking duplicate rules are still blocking the save. – smukov Nov 8 '18 at 13:54
0

Unfortunately you will have to roll something on your own leveraging DuplicateResult Class. Below is an example of vfpage that shows a custom application that lets users add a contact. When a contact is saved, an alert displays if there are duplicate records.

Page:

<apex:page controller="ContactDedupeController">
    <apex:form >
        <apex:pageBlock title="Duplicate Records" rendered="{!hasDuplicateResult}">
            <apex:pageMessages />
            <apex:pageBlockTable value="{!duplicateRecords}" var="item">
                <apex:column >
                    <apex:facet name="header">Name</apex:facet>
                    <apex:outputLink value="/{!item['Id']}">{!item['Name']}</apex:outputLink>
                </apex:column>
                <apex:column >
                    <apex:facet name="header">Owner</apex:facet>
                    <apex:outputField value="{!item['OwnerId']}"/>
                </apex:column>
                <apex:column >
                    <apex:facet name="header">Last Modified Date</apex:facet>
                    <apex:outputField value="{!item['LastModifiedDate']}"/>
                </apex:column>
            </apex:pageBlockTable> 
        </apex:pageBlock>

        <apex:pageBlock title="Contact" mode="edit">
            <apex:pageBlockButtons >
                <apex:commandButton value="Save" action="{!save}"/>
            </apex:pageBlockButtons>         

            <apex:pageBlockSection >
                <apex:inputField value="{!Contact.FirstName}"/>
                <apex:inputField value="{!Contact.LastName}"/>
                <apex:inputField value="{!Contact.Email}"/>
                <apex:inputField value="{!Contact.Phone}"/>
                <apex:inputField value="{!Contact.AccountId}"/>
            </apex:pageBlockSection>
        </apex:pageBlock>
    </apex:form>
</apex:page>

Controller:

public class ContactDedupeController {

    // Initialize a variable to hold the contact record you're processing
    private final Contact contact;

    // Initialize a list to hold any duplicate records
    private List<sObject> duplicateRecords;

    // Define variable that’s true if there are duplicate records
    public boolean hasDuplicateResult{get;set;}

    // Define the constructor
    public ContactDedupeController() {

        // Define the values for the contact you’re processing based on its ID
        Id id = ApexPages.currentPage().getParameters().get('id');
        this.contact = (id == null) ? new Contact() : 
            [SELECT Id, FirstName, LastName, Email, Phone, AccountId 
             FROM Contact WHERE Id = :id];

        // Initialize empty list of potential duplicate records
        this.duplicateRecords = new List<sObject>();
        this.hasDuplicateResult = false;
    }

    // Return contact and its values to the Visualforce page for display
    public Contact getContact() {
        return this.contact;
    }

    // Return duplicate records to the Visualforce page for display
    public List<sObject> getDuplicateRecords() {
        return this.duplicateRecords;
    }

    // Process the saved record and handle any duplicates
    public PageReference save() {

        // Optionally, set DML options here, use “DML” instead of “false” 
        //   in the insert()
        // Database.DMLOptions dml = new Database.DMLOptions(); 
        // dml.DuplicateRuleHeader.allowSave = true;
        // dml.DuplicateRuleHeader.runAsCurrentUser = true;
        Database.SaveResult saveResult = Database.insert(contact, false);

        if (!saveResult.isSuccess()) {
            for (Database.Error error : saveResult.getErrors()) {
                // If there are duplicates, an error occurs
                // Process only duplicates and not other errors 
                //   (e.g., validation errors)
                if (error instanceof Database.DuplicateError) {
                    // Handle the duplicate error by first casting it as a 
                    //   DuplicateError class
                    // This lets you use methods of that class 
                    //  (e.g., getDuplicateResult())
                    Database.DuplicateError duplicateError = 
                            (Database.DuplicateError)error;
                    Datacloud.DuplicateResult duplicateResult = 
                            duplicateError.getDuplicateResult();

                    // Display duplicate error message as defined in the duplicate rule
                    ApexPages.Message errorMessage = new ApexPages.Message(
                            ApexPages.Severity.ERROR, 'Duplicate Error: ' + 
                            duplicateResult.getErrorMessage());
                    ApexPages.addMessage(errorMessage);

                    // Get duplicate records
                    this.duplicateRecords = new List<sObject>();

                    // Return only match results of matching rules that 
                    //  find duplicate records
                    Datacloud.MatchResult[] matchResults = 
                            duplicateResult.getMatchResults();

                    // Just grab first match result (which contains the 
                    //   duplicate record found and other match info)
                    Datacloud.MatchResult matchResult = matchResults[0];

                    Datacloud.MatchRecord[] matchRecords = matchResult.getMatchRecords();

                    // Add matched record to the duplicate records variable
                    for (Datacloud.MatchRecord matchRecord : matchRecords) {
                        System.debug('MatchRecord: ' + matchRecord.getRecord());
                        this.duplicateRecords.add(matchRecord.getRecord());
                    }
                    this.hasDuplicateResult = !this.duplicateRecords.isEmpty();
                }
            }

            //If there’s a duplicate record, stay on the page
            return null;
        }

        //  After save, navigate to the view page:
        return (new ApexPages.StandardController(contact)).view();
    }

}

You need to do something like the above example to look for the duplicates in the onError or onSubmit in your lightning component and display the relevant details.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.