Apex Wrapper Class
1. What is a Wrapper Class?
A Wrapper Class is a custom class in Salesforce Apex that acts as a container to wrap one or
more objects or variables together. This is useful when you need to group different types of
data or add extra information to existing records (like checkboxes in UI).
Wrapper Class is used to create User Defined datatypes. It is a collection of data members
and doesnot contain any action.
2. Basic Syntax
public class MyWrapper {
public Account acc { get; set; }
public Boolean isSelected { get; set; } // Extra property for UI use
Explanation:
Term Meaning
public class MyWrapper Defines the custom wrapper class
Account acc Stores a single Account record
Boolean isSelected Used for checkbox selection (true/false)
{ get; set; } Apex property syntax to allow reading and writing
3. Use Cases
To add checkboxes next to records in a list (so users can select them).
To combine different objects (like showing Account and Contact info together).
To add extra fields just for display (like "isSelected" or "highlight") that aren't in the
original object.
To control which records to update or delete based on what the user selects.
4. Simple Use Case — Select Accounts with Checkbox
public class AccountWrapperCtrl {
public List<AccountWrapper> wrapList { get; set; }
public AccountWrapperCtrl() {
wrapList = new List<AccountWrapper>();
for (Account acc : [SELECT Id, Name FROM Account LIMIT 10]) {
[Link](new AccountWrapper(acc, false));
}
}
public class AccountWrapper {
public Account acc { get; set; }
public Boolean isSelected { get; set; }
public AccountWrapper(Account a, Boolean selected) {
[Link] = a;
[Link] = selected;
}
}
Explanation:
Element Meaning
wrapList List of wrapped records
AccountWrapper Inner class that holds Account + checkbox
isSelected Indicates which record was selected on UI
5. Wrapper with Multiple Objects
Scenario: Show Contact and Account info in one table
public class ContactAccountWrapperCtrl {
public List<ContactAccountWrapper> wrapList { get; set; }
public ContactAccountWrapperCtrl() {
wrapList = new List<ContactAccountWrapper>();
for (Contact con : [SELECT Id, FirstName, LastName, [Link] FROM Contact
LIMIT 10]) {
[Link](new ContactAccountWrapper(con, [Link]));
}
}
public class ContactAccountWrapper {
public Contact con { get; set; }
public Account acc { get; set; }
public ContactAccountWrapper(Contact c, Account a) {
[Link] = c;
[Link] = a;
}
}
Note: Use [Link] in SOQL to get related account inline.
6. Wrapper with Custom Logic
Scenario: List of Opportunities with amount > 100k and a status flag
public class OppWrapperCtrl {
public List<OppWrapper> wrapList { get; set; }
public OppWrapperCtrl() {
wrapList = new List<OppWrapper>();
for (Opportunity opp : [SELECT Id, Name, Amount FROM Opportunity WHERE Amount
> 100000]) {
[Link](new OppWrapper(opp));
}
}
public class OppWrapper {
public Opportunity opp { get; set; }
public Boolean isHighValue { get; set; }
public OppWrapper(Opportunity o) {
[Link] = o;
[Link] = [Link] > 200000; // Custom logic
}
}
7. Wrapper with Selection + Processing
Scenario: User selects Accounts → Submit → Update only selected records
public class AccountSelectCtrl {
public List<Wrapper> wrapList { get; set; }
public AccountSelectCtrl() {
wrapList = new List<Wrapper>();
for (Account a : [SELECT Id, Name FROM Account LIMIT 10]) {
[Link](new Wrapper(a));
}
}
public void processSelected() {
List<Account> selectedAccounts = new List<Account>();
for (Wrapper wrap : wrapList) {
if ([Link]) {
[Link] += ' - Updated';
[Link]([Link]);
}
}
update selectedAccounts;
}
public class Wrapper {
public Account acc { get; set; }
public Boolean isSelected { get; set; }
public Wrapper(Account a) {
[Link] = a;
[Link] = false;
}
}
8. LWC + Wrapper Class Use
Wrapper classes are commonly used when working with Apex controllers in Lightning Web
Components (LWC), like this:
public class ContactWrapCtrl {
@AuraEnabled(cacheable=true)
public static List<ContactWrapper> getContacts() {
List<ContactWrapper> results = new List<ContactWrapper>();
for (Contact c : [SELECT Id, Name, Email FROM Contact]) {
[Link](new ContactWrapper(c, 'Active'));
}
return results;
}
public class ContactWrapper {
@AuraEnabled public Contact con { get; set; }
@AuraEnabled public String status { get; set; }
public ContactWrapper(Contact c, String status) {
[Link] = c;
[Link] = status;
}
}
LWC will receive this object and display it in a data table.
Best Practices
✅ Do ✅ Don’t
Use inner wrapper class if only used in that Overuse wrappers for simple cases
controller
Keep wrapper fields @AuraEnabled for LWC Return raw SObjects when customization is
needed
Use custom flags like isSelected, status Overload wrapper with too much unrelated
logic
Make wrappers Serializable if storing in Avoid using static wrapper lists in non-static
ViewState methods