Tag Archives: Validation Rule

Handle Trigger and Validation Rule Error in Lightning Component

Sometimes we can have a requirement to display validation rule error or apex trigger error messages, on save of record in Lightning Component. We can handle those errors from apex controller and can throw messages to Lightning Component. In lightning response object though the state value comes as ERROR but the message in the error object always says ‘Internal Server Error”. Here is an example to handle the Trigger and Validation Rule Error in apex controller to show error messages in Lightning Component.

In below example I’ve used Lead object FirstName, LastName, Email & Company Field in lightning component to create record. And I’ve created a validation rule and a trigger validation on Lead object.

1. Validation rule for Company field (Company cannot be Test Company).

2. In below Trigger I’m checking if FirstName field value is “Test” then it will throw error.

trigger LeadTrigger on Lead (before insert, before update) {
    
    for(Lead obj :Trigger.new){
        if(obj.FirstName == 'Test'){
            obj.FirstName.addError('First name cannot be test');
        }
    }
}

Apex Controller:

public class SampleAuraController {
    
    @AuraEnabled
    Public static void createLead(Lead objLead){
        String msg = '';
        try{
            //Insert Lead Record
            insert objLead; 
            
        }catch(DmlException e){
            //Any type of Validation Rule error message, Required field missing error message, Trigger error message etc..
            //we can get from DmlException
            
            //Get All DML Messages
            for (Integer i = 0; i < e.getNumDml(); i++) {
                //Get Validation Rule & Trigger Error Messages
                msg =+ e.getDmlMessage(i) +  '\n' ;
            }
            //throw DML exception message
            throw new AuraHandledException(msg);
            
        }catch(Exception e){
            //throw all other exception message
            throw new AuraHandledException(e.getMessage());
        }
        finally {
        }
    } 
}

Lightning Component:

<!--Sample.cmp--> 
<aura:component controller="SampleAuraController" implements="flexipage:availableForAllPageTypes,force:appHostable">
    
    <!--Declare Attributes-->
    <aura:attribute name="isSpinner" type="boolean" default="false"/>
    <aura:attribute name="objLead" type="Lead" default="{'sobjectType':'Lead', 
                                                        'FirstName': '',
                                                        'LastName': '',
                                                        'Email': '', 
                                                        'Company': ''}"/>
    
    
    <!--Component Start--> 
    <div class="slds-m-around--xx-large">
        <div class="container-fluid">
            <div class="form-group">
                <lightning:input name="fname" type="text" maxlength="50" required="true" label="First Name" value="{!v.objLead.FirstName}" />
            </div>
            <div class="form-group">
                <lightning:input name="lname" type="text" maxlength="50" required="true" label="Last Name" value="{!v.objLead.LastName}" />
            </div>
            <div class="form-group">
                <lightning:input name="emailId" type="email" maxlength="100" required="true" label="Email" value="{!v.objLead.Email}" />
            </div>
            <div class="form-group">
                <lightning:input name="company" type="text" maxlength="50" required="true" label="Company" value="{!v.objLead.Company}" />
            </div>
        </div>
        <br/>
        <lightning:button variant="brand" label="Submit" onclick="{!c.handleLeadSave}" />        
        <lightning:button label="Cancel" onclick="{!c.handleCancel}"/>        
    </div>
    <!--Component End-->
</aura:component>

Lightning JS Controller:

({    
    //Handle Lead Save
    handleLeadSave : function(component, event, helper) {
        var objLead = component.get("v.objLead");
        var action = component.get("c.createLead");
        action.setParams({
            objLead : objLead
        });
        action.setCallback(this,function(a){
            var state = a.getState();
            if(state === "SUCCESS"){
                alert('Record is Created Successfully');
            } else if(state === "ERROR"){
                var errors = action.getError();
                if (errors) {
                    if (errors[0] && errors[0].message) {
                        alert(errors[0].message);
                    }
                }
            }else if (status === "INCOMPLETE") {
                alert('No response from server or client is offline.');
            }
        });       
        $A.enqueueAction(action);
    }
})

Output:

Trigger Error Message:

Validation Rule Error Message:

ISBLANK and ISNULL with a Rich Text Field is not working in Validation Rule

Using ISBLANK or ISNULL with a Rich Text Area field always returns true when used in a Validation Rule.
To check whether a Rich Text Area field is empty, use the LEN function.

LEN (Rich_Text_Field__c) = 0

Create One to One Relationship in Salesforce

Basically Salesforce offers two types of relationship:

  • One To Many Relationship
  • Many To Many Relationship (Using the concept of Junction object)

Sometimes we may need One To One relationship, But unfortunately Salesforce doesn’t allow any direct methodology to build One To one relationship.

Let’s consider the scenario that we want to establish a One to One relationship between two custom objects Employee__c and PAN_Card__c.

So, here are few ways to implement One To One relationship between two objects in Salesforce. We can achieve this by using configuration only and can also achieve this by using code to make it more scalable.

Option 1:

  • Create a lookup field on PAN_Card__c to Employee__c.
  • Create a custom field on the PAN_Card__c object and make the field unique. This field would be used to hold the ID of the associated Employee__c. Hide this field from all page layouts.
  • Create a Workflow rule on PAN_Card__c. For any change of the lookup field on PAN_Card__c object, update the custom field on the PAN_Card__c object with the value of the associated Employee Id.

We have established a one to one relationship between PAN_Card__c and Employee__c. When we try to add a second PAN_Card__c to the Employee__c, the “unique” constraint would be violated and an error would be thrown. This approach will work on both standard and custom object.

Option 2:

  • Create a master detail relationship on PAN_Card__c to Employee__c object.
  • Create a roll up summary field on Employee__c object of PAN_Card__c with count type.
  • Create a validation rule on Employee__c object rollup summary field to check if count > 1.

In this way also, We have established a one to one relationship between PAN_Card__c and Employee__c. So it will throw an error if Employee__c has more than one PAN Card.

Option 3:

  • Create lookup fields on both objects PAN_Card__c and Employee__c, to each other.
  • Write triggers, for any change on these lookups, to either copy the record ID into the other object’s lookup field when the other object’s lookup field is empty, or disallow the change to the original record when the other object’s lookup field is already populated with a different ID from the original record.

This is already having a one-to-onePassport relation.

Option 4:

  • Create a trigger on PAN_Card__c object to check if the PAN Card record already exists for an Employee. If it exist, then throw an error, else allow the user to create.
    Here is the example for Employee__c and PAN_Card__c object:

    trigger PANCardValidation on PAN_Card__c (before insert, before update) {
        Set<id> employeeIds = new Set<id>();
        Map<id, Employee__c> mapEmployee = new Map<id, Employee__c>();
     
        for (PAN_Card__c p : trigger.New) {
            employeeIds.add(p.Employee__c);
        }
     
        List<Employee__c> lstEmployee = [SELECT Id, Name FROM Employee__c WHERE Id IN : employeeIds];
        if (!lstEmployee.isEmpty()) {
            for (Employee__c emp : lstEmployee) {
                mapEmployee.put(emp.Id, emp);
            }
     
            for (PAN_Card__c p : trigger.New) {
                if (mapEmployee.containsKey(p.Employee__c)) {
                    p.addError('A PAN Card already exist for the employee - ' + mapEmployee.get(p.Employee__c).Name);
                }
            }
        }
    }
    

Display of Validation Rule Error on Visualforce Page

Here I’ve a custom “Student__c” object. There is a validation rule on “Date_of_Birth__c” field, that Date of Birth cannot be greater than today. And I’m using a visualforce page to insert the data in “Student__c” object. So, I need to show the validation rule error message in visualforce page.

Validation Rule:

Below is my controller which gave the solution for displaying validation error message on visualforce page.

Controller:

public with sharing class StudentExt {

    public Student__c student{get;set;}
    
    public StudentExt(ApexPages.StandardController controller) {
        student = (Student__c)controller.getRecord();
    }
    
    public Pagereference saveStudent() {
        try {
            Upsert student;
            return new Pagereference('/' + student.Id);
        }
        catch(DMLException de) {
            Apexpages.addMessage(new ApexPages.Message(ApexPages.SEVERITY.FATAL, de.getDmlMessage(0)));
            return NULL;
        }
        catch(Exception e) {
            Apexpages.addMessage(new ApexPages.Message(ApexPages.SEVERITY.FATAL, e.getMessage()));
            return NULL;
        }
    }
}

Visualforce Page

<apex:page standardController="Student__c" extensions="StudentExt" >
    <apex:pageMessages id="errormsg" />
    <apex:form >
        <apex:pageBlock >
            <apex:pageBlockButtons >
                <apex:commandButton value="Save" action="{!saveStudent}" reRender="errormsg"/>
                <apex:commandButton value="Cancel" action="{!Cancel}"/>
            </apex:pageBlockButtons>
            
            <apex:pageBlockSection columns="2" title="Information">
                <apex:inputField value="{!Student__c.First_Name__c}"/>
                <apex:inputField value="{!Student__c.Last_Name__c}"/>
                <apex:inputField value="{!Student__c.Date_of_Birth__c}"/>
                <apex:inputField value="{!Student__c.Address__c}"/>
            </apex:pageBlockSection>
        </apex:pageBlock>
    </apex:form>
</apex:page>