Intermediate 30 min read

Build the Trigger Handler

By the end of this lesson, you'll be able to:

  • Write a thin trigger routing to a handler class, following Module 24's pattern
  • Implement the handler's afterUpdate method for the basic case
  • Explain why Trigger.oldMap is needed for this specific requirement

Prerequisites: "Design the Requirement"

The thin trigger

trigger OpportunityTrigger on Opportunity (after update) {
    new OpportunityTriggerHandler().afterUpdate(Trigger.new, Trigger.oldMap);
}

Exactly Module 24's "Avoiding Logic in Triggers" pattern — the trigger itself does nothing but hand off to the handler, passing both Trigger.new and Trigger.oldMap since this requirement needs to compare old and new values.

Detecting the actual change

public class OpportunityTriggerHandler {
    public void afterUpdate(List<Opportunity> newOpportunities, Map<Id, Opportunity> oldMap) {
        for (Opportunity opp : newOpportunities) {
            Opportunity oldOpp = oldMap.get(opp.Id);
            Boolean justWon = opp.StageName == 'Closed Won' && oldOpp.StageName != 'Closed Won';
            Boolean justUnwon = opp.StageName != 'Closed Won' && oldOpp.StageName == 'Closed Won';

            if (justWon) {
                System.debug('Opportunity ' + opp.Id + ' just became Closed Won.');
            }
            if (justUnwon) {
                System.debug('Opportunity ' + opp.Id + ' is no longer Closed Won.');
            }
        }
    }
}

This is Module 24's Trigger.oldMap lesson doing real work: justWon and justUnwon distinguish "actually changed into/out of Closed Won" from "was already Closed Won and something unrelated changed" — the exact comparison this requirement depends on.

Why this comparison matters

Without comparing against oldMap, every update on an Opportunity already sitting at Closed Won (say, just updating its description) would look identical to one that just became Closed Won — double-counting the same Amount into the rollup every time the record is touched. Catching only the actual transition is what keeps the rollup correct over time.

Exercise

Given opp and oldOpp, write a Boolean expression amountChanged that is true only when the Amount field's value actually changed.

Show hint

opp.Amount != oldOpp.Amount

APEX

Build the Trigger Handler Quiz

1. Why compare opp.StageName against oldMap.get(opp.Id).StageName instead of just checking opp.StageName == 'Closed Won'?

Log in to submit the quiz and save your score.

My Notes

Log in to keep private notes on this lesson.

Questions about this lesson

No questions yet — be the first to ask.

Log in to ask a question about this lesson.

Summary

This lesson writes the trigger and handler skeleton, detecting exactly when an Opportunity newly becomes (or stops being) Closed Won.