Returning Data to LWC: Wrapper Classes and DTOs
By the end of this lesson, you'll be able to:
- Return a custom wrapper class from an @AuraEnabled method
- Explain why a DTO shape sometimes fits better than returning a raw sObject
- Apply Module 16's wrapper class pattern to the LWC boundary specifically
Prerequisites: "Imperative Calls vs the Wire Service (the Apex Side)"
Returning a raw sObject: the simple case
@AuraEnabled
public static List<Account> getAccounts() {
return [SELECT Id, Name, Industry FROM Account];
}
@AuraEnabled— marks the method.public static List<Account> getAccounts() {— for a component that just needs to display realAccountfields directly.return [SELECT Id, Name, Industry FROM Account];— returning the queriedsObjectList is simple and works fine — exactly like every SOQL example since Module 20.}— closes the method.
When a wrapper class fits better
public class AccountSummary {
@AuraEnabled public String name;
@AuraEnabled public Integer openOpportunityCount;
@AuraEnabled public Decimal totalWonRevenue;
}
@AuraEnabled
public static List<AccountSummary> getAccountSummaries() {
List<AccountSummary> summaries = new List<AccountSummary>();
for (Account acc : [SELECT Id, Name, Total_Won_Revenue__c, (SELECT Id FROM Opportunities WHERE IsClosed = false) FROM Account]) {
AccountSummary summary = new AccountSummary();
summary.name = acc.Name;
summary.openOpportunityCount = acc.Opportunities.size();
summary.totalWonRevenue = acc.Total_Won_Revenue__c;
summaries.add(summary);
}
return summaries;
}
public class AccountSummary {— this is Module 16's wrapper-class pattern, applied at the LWC boundary.@AuraEnabled public String name;— a real field.@AuraEnabled public Integer openOpportunityCount;— a computed value.@AuraEnabled public Decimal totalWonRevenue;— a rollup (Module 26).}— closes the wrapper class.- (blank line)
@AuraEnabled— marks the method.public static List<AccountSummary> getAccountSummaries() {— returns the wrapper, not a rawsObject.List<AccountSummary> summaries = new List<AccountSummary>();— collects the results.- (blank line)
for (Account acc : [SELECT Id, Name, Total_Won_Revenue__c, (SELECT Id FROM Opportunities WHERE IsClosed = false) FROM Account]) {— the child-relationship subquery, Module 20.AccountSummary summary = new AccountSummary();— builds one wrapper per account.summary.name = acc.Name;— the real field.summary.openOpportunityCount = acc.Opportunities.size();— the computed value, from the subquery.summary.totalWonRevenue = acc.Total_Won_Revenue__c;— the rollup.summaries.add(summary);— collects it.}— closes the loop.- (blank line)
return summaries;— hands back a shape no single query alone could return directly, tailored to exactly what a dashboard component needs to display.}— closes the method.
Every field the UI needs also gets @AuraEnabled
Notice @AuraEnabled appears on the fields of AccountSummary, not just the method — each field the UI needs to read must be individually exposed too, the same annotation-based exposure principle from Lesson 2, now applied one level deeper.
Exercise
Write a wrapper class ContactSummary with @AuraEnabled fields fullName and email, and a method returning a List<ContactSummary> built from queried Contacts.
Show hint
Remember @AuraEnabled on both the fields and the method.
Returning Data to LWC: Wrapper Classes and DTOs Quiz
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
An @AuraEnabled method doesn't have to return a raw sObject — a custom wrapper class (or DTO, "Data Transfer Object") often shapes the data more usefully for exactly what the UI needs to display.