Apex Triggers for Custom Validations

Kris Sparks
3 min readNov 8, 2017

Salesforce has built-in validations that can be applied to specific fields, but these validations are somewhat rigid and limited. When searching for programatic solutions there seemed to be confusion and hesitancy regarding using triggers and custom validations. Once I figured out the solution, however, I found that they are relatively easy to build and limitless in versatility.

Two reasons to build custom validations are extensibility and searchability. We can add features and conditions to our validation at a later date. Additionally, everything is the codebase is easily searchable which makes debugging a less painful task.

It might help if you already understand:

- Salesforce development

- Apex Triggers

Let’s say our business has distribution centers across the country. We may want our employees to be able to update data on the Center__c object, but we only want the system administrator and center managers to be able to change the name of a center. If the name of a center is inadvertently changed it can cause chaos (true story).

The first thing we’ll do is create a trigger on the Center__c object:

trigger Center on Center__c (before update) {
}

Let’s create a set of profile names that we want to be able to edit the Center__c.Name field:

trigger Center on Center__c (before update) {
private Set<String> authorizedProfiles = new Set<String>{
'System Administrator',
'Center Manager'
};
}

Then let’s get the profile ID of the current user:

trigger Center on Center__c (before update) {
private Set<String> authorizedProfiles = new Set<String>{
'System Administrator',
'Center Manager'
};
private Id profileId = userInfo.getProfileId();
}

Now we can query for the user’s profile name using the profile ID:

trigger Center on Center__c (before update) {
private Set<String> authorizedProfiles = new Set<String>{
'System Administrator',
'Center Manager'
};
private Id profileId = userInfo.getProfileId();
private String profileName = [SELECT Name
FROM Profile
WHERE Id = :profileId
].Name;
}

NOTE: We could just use the profile ID, but for readability we are using the profile name.

Now that we have our variables set we can write our validation. We are going to start by checking the new user input before the records are updated. (Notice the before update trigger event the arguments at the top of the trigger.) For this new method we’ll use the isUpdate method:

trigger Center on Center__c (before update) {
private Set<String> authorizedProfiles = new Set<String>{
'System Administrator',
'Center Manager'
};
private Id profileId = userInfo.getProfileId();
private String profileName = [SELECT Name
FROM Profile
WHERE Id = :profileId
].Name;
if(Trigger.isUpdate){
}
}

Next we’ll iterate through all the centers using a for loop:

trigger Center on Center__c (before update) {
private Set<String> authorizedProfiles = new Set<String>{
'System Administrator',
'Center Manager'
};
private Id profileId = userInfo.getProfileId();
private String profileName = [SELECT Name
FROM Profile
WHERE Id = :profileId
].Name;
if(Trigger.isUpdate){
for(Center__c center : Trigger.new) {
}
}
}

And finally we’ll implement our conditional statements. It reads like this:

  1. If the existing (old) center name is not equal to the new center name*
  2. And the authorizedProfiles set does not contain the profile name of the user
  3. Let the user know they cannot update the record

Note: At the .addError method it will exit and the record will not be updated.

trigger Center on Center__c (before update) {
private Set<String> authorizedProfiles = new Set<String>{
'System Administrator',
'Center Manager'
};
private Id profileId = userInfo.getProfileId();
private String profileName = [SELECT Name
FROM Profile
WHERE Id = :profileId
].Name;
if(Trigger.isUpdate){
for(Center__c center : Trigger.new)
if(Trigger.oldMap.get(center.Id).Name != center.Name &&
!authorizedProfiles.contains(profileName)) {
center.Name.addError('You do not have permission '
+ 'to change the name of a center');
}
}
}

This is one way we can handle custom validations on object updates.

The following post was helpful in figuring this out and may be a useful resource:

We hope this helps.

As always, feel free to leave kind comments, suggestions, corrections and alternate/better solutions!

*You may notice we did not use Trigger.newMap since we already have access to the new center information because we are iterating over the new objects using Trigger.new

--

--