Mastering Salesforce Development: Apex Trigger and Class for Counting Child Records with Lookup Relationships

Himanshu Varshney
Senior Salesforce Developer
February 2, 2024

childparent

Apex Trigger: This will be triggered whenever a child record is inserted, updated, or deleted. It will call an Apex Class method to update the count on the parent record.

Apex Class: This class will contain methods to handle the logic for counting the child records and updating the parent record accordingly.

Assuming we have two objects, Parent__c and Child__c, where Child__c has a lookup relationship to Parent__c through a field named Parent__c, and the Parent__c object has a field to store the count of child records named Child_Count__c.


Apex Trigger

trigger ChildTrigger on Child__c (after insert, after update, after delete, after undelete) {
    if (Trigger.isAfter) {
        if (Trigger.isInsert || Trigger.isUndelete) {
            ChildHandler.updateParentCount(Trigger.newMap.keySet(), 'add');
        } else if (Trigger.isDelete) {
            ChildHandler.updateParentCount(Trigger.oldMap.keySet(), 'subtract');
        } else if (Trigger.isUpdate) {
            // For updates, we need to check if the Parent__c field was changed, and then update counts accordingly
            Set<Id> oldParentIds = new Set<Id>();
            Set<Id> newParentIds = new Set<Id>();
            for (Child__c child : Trigger.new) {
                Child__c oldChild = Trigger.oldMap.get(child.Id);
                if (child.Parent__c != oldChild.Parent__c) {
                    if (oldChild.Parent__c != null) oldParentIds.add(oldChild.Parent__c);
                    if (child.Parent__c != null) newParentIds.add(child.Parent__c);
                }
            }
            ChildHandler.updateParentCount(oldParentIds, 'subtract');
            ChildHandler.updateParentCount(newParentIds, 'add');
        }
    }
}


Apex Class

public class ChildHandler {
    public static void updateParentCount(Set<Id> parentIds, String operation) {
        if (!parentIds.isEmpty()) {
            List<Parent__c> parentsToUpdate = new List<Parent__c>();
            for (AggregateResult ar : [
                SELECT Parent__c, COUNT(Id) count
                FROM Child__c
                WHERE Parent__c IN :parentIds
                GROUP BY Parent__c
            ]) {
                Id parentId = (Id)ar.get('Parent__c');
                Integer count = (Integer)ar.get('count');
                Parent__c parent = new Parent__c(Id = parentId);

                if (operation == 'add') {
                    parent.Child_Count__c = count;
                } else if (operation == 'subtract') {
                    parent.Child_Count__c = count - 1; // Assuming the trigger context already removed one child
                }

                parentsToUpdate.add(parent);
            }

            if (!parentsToUpdate.isEmpty()) {
                update parentsToUpdate;
            }
        }
    }
}


Explanation

Trigger: The trigger ChildTrigger is set to fire after insert, update, delete, and undelete operations on Child__c records. Depending on the operation, it calls the updateParentCount method with appropriate parameters.

Apex Class: The ChildHandler class has the updateParentCount method that accepts a set of parent IDs and an operation ('add' or 'subtract'). It queries the Child__c records grouped by Parent__c to get the count, then updates the Parent__c records' Child_Count__c field accordingly.

Make sure to add appropriate error handling and bulkify your code to handle large data volumes efficiently. Also, consider using custom settings or custom metadata types if you need to make your trigger more configurable.

Share this article:
View all articles

Related Articles

AGENTS.md: The Open Standard That's Changing How AI Coding Agents Work With Your Codebase featured image
April 10, 2026
AGENTS.md is a simple but powerful open standard — a dedicated Markdown file that gives AI coding agents like Claude Code, Cursor, and GitHub Copilot the project-specific context they need to work effectively. Adopted by 60,000+ projects and governed by the Linux Foundation, it's becoming essential infrastructure for AI-assisted development.
Everything Your Dental Practice Needs to Grow Online — In One Package featured image
April 10, 2026
Most dental practices are juggling 3 or 4 vendors to handle their website, marketing, and patient communications. Anablock bundles everything into one package — website development, digital marketing, and AI-powered patient support chatbots — built specifically for dental clinics.
LangChain Deep Agents vs Claude Managed Agents: Which Should You Build With? featured image
April 10, 2026
LangChain Deep Agents Deploy and Anthropic Claude Managed Agents launched within 24 hours of each other in April 2026. Both target the same problem — production-ready AI agents — but take fundamentally different approaches. Here's the full breakdown: architecture, features, pricing, and which one to choose.

Unlock the Full Power of AI-Driven Transformation

Schedule Demo

See how Anablock can automate and scale your business with AI.

Book Demo

Start a Support Agent

Talk directly with our AI experts and get real-time guidance.

Call Now

Send us a Message

Summarize this page content with AI