12.2 Aura Component Structure & Resources
Key Takeaways
- An Aura component is a bundle of resources: component markup, controller, helper, style, design, documentation, renderer, and optional SVG
- aura:attribute defines typed public/private data on the component; expressions bind attributes into markup
- Client-side controller methods handle UI events; helpers hold shared JavaScript logic; server-side Apex controllers use @AuraEnabled methods
- Component events target ancestors in the containment hierarchy; application events broadcast more widely—prefer component events when a parent-child path exists
- Platform Developer I may still test Aura structure conceptually even though LWC is preferred for new UI
12.2 Aura Component Structure & Resources
Quick Answer: An Aura component is a bundle of files: component markup, controller (client JS), helper, style (CSS), design, documentation, optional renderer, and optional SVG. Data is declared with
aura:attribute. UI actions call the client controller (often delegating to a helper); server work uses an Apex controller with@AuraEnabled. Component events bubble to parents; application events are broader. Know this structure even if you build new UI in LWC.
Section 12.1 established LWC as the modern default. This section covers Aura literacy the exam still expects: what lives in a bundle, how attributes work, how client and server controllers split responsibilities, and how Aura events differ.
The Aura Component Bundle
In the Developer Console or metadata, an Aura component is a folder-like bundle, not a single file. Typical resources:
| Resource | Role |
|---|---|
Component (.cmp) | Markup: HTML-like tags, aura:attribute, aura:handler, nested components, expressions {!v.attr} / {!c.action} |
Controller (.js) | Client-side JavaScript action handlers bound to UI events |
Helper (.js) | Shared client-side functions; controllers stay thin and call helpers |
Style (.css) | Component-scoped CSS (Aura scoping conventions apply) |
Design (.design) | App Builder exposure: which attributes admins can set on the page |
Documentation (.auradoc) | Description and samples for component library docs |
Renderer (.js) | Optional custom rendering lifecycle overrides (advanced; rarely the first choice) |
| SVG | Optional custom icon for App Builder / component palette |
Exam tip: Match the resource to the job. “Make an attribute editable in App Builder” → design. “Share logic between two controller actions” → helper. “Call Apex” → Apex class with @AuraEnabled, invoked from the client controller/helper—not from the .cmp file directly as raw Apex code.
Minimal markup shape
<!-- c:accountPanel.cmp -->
<aura:component controller="AccountPanelController" implements="flexipage:availableForRecordHome,force:hasRecordId">
<aura:attribute name="recordId" type="String" />
<aura:attribute name="accountName" type="String" />
<aura:handler name="init" value="{!this}" action="{!c.doInit}" />
<lightning:card title="{!v.accountName}">
<lightning:button label="Refresh" onclick="{!c.handleRefresh}" />
</lightning:card>
</aura:component>
Key ideas in that snippet:
controller="AccountPanelController"points at the Apex server controller class nameimplementsinterfaces control where the component can be placed (for example record pages) and which platform attributes (likerecordId) are availableaura:handler name="init"runs client logic when the component initializes{!v.accountName}reads a view attribute;{!c.handleRefresh}references a client controller action
Attributes
aura:attribute declares typed data on the component:
<aura:attribute name="contacts" type="Contact[]" />
<aura:attribute name="maxRows" type="Integer" default="10" />
<aura:attribute name="showPanel" type="Boolean" default="true" access="private" />
| Concern | Detail |
|---|---|
| Name | Referenced as v.name in expressions |
| Type | Primitives, sObjects, lists, custom Apex types (with caveats), component references |
| default | Initial value |
| access | public (default for many cases), private, global—affects who can set/see the attribute |
| required | Whether the attribute must be provided |
Attributes are the Aura analogue of LWC public/@api properties and internal fields. Parent components set child attributes in markup:
<c:childPanel maxRows="{!v.pageSize}" />
Design attributes in the .design file surface selected attributes to Lightning App Builder so admins can configure the component without code.
Client Controller vs Helper vs Server Controller
Client-side controller
The client controller maps UI events to functions:
// accountPanelController.js
({
doInit: function (component, event, helper) {
helper.loadAccount(component);
},
handleRefresh: function (component, event, helper) {
helper.loadAccount(component);
}
})
Signature pattern to recognize: function (component, event, helper).
component: read/write attributes (component.get("v.accountName"),component.set(...))event: source event datahelper: shared helper methods
Helper
Helpers avoid duplicating logic across multiple controller actions and keep controllers readable:
// accountPanelHelper.js
({
loadAccount: function (component) {
var action = component.get("c.getAccount");
action.setParams({ accountId: component.get("v.recordId") });
action.setCallback(this, function (response) {
var state = response.getState();
if (state === "SUCCESS") {
component.set("v.accountName", response.getReturnValue().Name);
} else if (state === "ERROR") {
// surface errors to the user
}
});
$A.enqueueAction(action);
}
})
Pattern to memorize:
component.get("c.apexMethodName")— c. here means server Apex method, not the client controllersetParams→setCallback→$A.enqueueAction(action)- Check
response.getState()forSUCCESS,ERROR,INCOMPLETE
Server-side (Apex) controller
public with sharing class AccountPanelController {
@AuraEnabled
public static Account getAccount(Id accountId) {
return [
SELECT Id, Name
FROM Account
WHERE Id = :accountId
LIMIT 1
];
}
}
Rules that show up on exams and code reviews:
- Methods called from Aura/LWC must be
@AuraEnabled(and oftenstaticfor these controllers) - Prefer
with sharingunless there is a deliberate system-context reason otherwise - Enforce CRUD/FLS as appropriate for the data exposure
- Return serializable types; avoid patterns that cannot travel over the wire cleanly
Client vs server split: UI state, show/hide, and simple calculations stay client-side. Database access, security-sensitive decisions, and complex business rules belong on the server.
Events: Component vs Application (High Level)
Aura’s event model is a frequent conceptual question.
Component events
- Defined with a component event type and fired by a child
- Travel through the containment hierarchy (bubble/capture toward parents)
- Best when a parent (or ancestor) should handle the child’s notification
- Lower coupling blast radius than application events
Application events
- Broadcast more like a pub-sub channel across the app (handlers register interest)
- Useful when components are not in a direct parent-child relationship
- Easier to create surprising cross-talk if overused
Exam heuristic: If the communication path is parent ↔ child, choose a component event (or, in modern LWC, CustomEvent). If components are siblings or distant and must coordinate, application events (Aura) or Lightning Message Service (modern) are the conceptual match.
<!-- Child fires a component event; parent declares aura:handler -->
<aura:handler name="saveComplete" event="c:saveCompleteEvent" action="{!c.onSaveComplete}" />
Renderer and Other Advanced Bundle Pieces
The renderer lets you override default DOM rendering lifecycle methods. On PDI, treat custom renderers as advanced / rare. Prefer standard markup binding and base components. SVG resources customize the icon shown in builders. Documentation resources matter for team libraries, not typically for deep exam calculation.
When the Exam Still Asks Aura Structure
Expect Aura-oriented items when the question:
- Shows a bundle file list and asks which file holds App Builder-exposed attributes → design
- Asks where shared client JavaScript should live → helper
- Shows
{!c.doSomething}vs{!v.field}and asks what each means → client action vs attribute - Contrasts component events and application events
- Mentions
$A.enqueueActionorresponse.getState() - Describes an existing Aura component that must be extended or diagnosed
You may also see “which interface makes the component available on a record page?”-style questions (flexipage:availableForRecordHome, force:hasRecordId, and similar implements values).
Aura vs LWC Mapping (Study Aid)
| Aura concept | Rough LWC analogue |
|---|---|
.cmp markup | .html template |
| Client controller + helper | .js class methods |
aura:attribute | fields / @api properties |
Apex @AuraEnabled + enqueueAction | @wire or imperative Apex |
| Component event | CustomEvent |
| Application event | LMS / pub-sub pattern |
.design | js-meta.xml targets + properties |
| Style resource | .css (Shadow DOM scoped in LWC) |
Use this table to transfer knowledge—not to assume APIs are interchangeable. Markup and lifecycles differ.
Practical Pitfalls
- Forgetting
$A.enqueueActionso the server call never runs - Mutating attributes incorrectly or expecting two-way binding everywhere without handlers
- Putting heavy logic only in the controller and duplicating it across actions instead of using a helper
- Using application events for simple parent-child communication
- Assuming client-side checks replace sharing and FLS on Apex
Bottom line: An Aura component is a multi-file bundle. Know component / controller / helper / style / design / documentation / renderer / SVG, aura:attribute, the client controller + helper + @AuraEnabled Apex path, and component vs application events. Even as LWC dominates new work, these Aura structures still appear on Platform Developer I at a conceptual level.
A developer wants admins to set a title string on an Aura component when they place it on a Lightning record page in App Builder. Which Aura bundle resource is primarily used to expose that attribute for configuration?
Which sequence correctly invokes an Apex method from an Aura client-side helper?
When should an Aura component event be preferred over an application event?