Capture case details quickly from the Service Console using a Utility Action LWC and an Aura wrapper. Perfect for call-center agents who need to record information before contact records finish loading.
Overview
Call center agents often need to capture case details while on a call — sometimes before a Contact record has fully loaded. Using a Utility Action in the Salesforce Service Console, we can open a lightweight window (utility bar) running a Lightning Web Component (LWC) wrapped in an Aura component so the recordId is reliably available. This pattern helps agents capture details immediately and associate cases to contacts once the contact loads.
Why use an Aura wrapper?
Although LWC is the recommended UI framework, LWC can sometimes fail to receive recordId reliably when launched as a utility item. An Aura wrapper that implements force:hasRecordId can capture the recordId and pass it to the LWC, ensuring consistent behavior.
Key features
- Openable as a utility action (separate window) so agents can multitask.
- Capture case details while waiting for contact load.
- Search/associate contact by PII (SSN, DOB, Name) and link the case when contact is available.
- Validate context and prevent saving when not on a Contact record.
Implementation summary
The solution includes three pieces:
- Aura component wrapper — captures and forwards the recordId.
- Lightning Web Component (LWC) — UI form and logic to create the Case via Apex.
- Apex controller — simple @AuraEnabled method to insert the case.
Aura component
Create an Aura component that implements force:hasRecordId and the utility interface, then pass the recordId to the LWC:
<aura:component
implements="force:hasRecordId,flexipage:availableForAllPageTypes,lightning:utilityItem">
<aura:attribute name="recordId" type="String" />
<aura:handler name="init" value="{!this}" action="{!c.doInit}" />
<c:createCaseUtility contactId="{!v.recordId}"/>
</aura:component>
({
doInit: function (component, event, helper) {
var recordId = component.get("v.recordId");
if (!recordId) {
console.warn("Record ID is undefined. Ensure the utility is launched from a record context.");
} else {
console.log("Record ID retrieved:", recordId);
}
}
});
Lightning Web Component (LWC)
The LWC renders a compact case-entry form and calls Apex to insert the Case. Important parts include:
- Properties to hold form values and the current recordId.
- Wired
getRecordto fetch Contact fields when recordId is present. - Validation to ensure the recordId is a Contact (
startsWith('003')). - Minimize support using
lightning/platformUtilityBarApi.
<template>
<lightning-card>
<div class="slds-m-left_small slds-m-right_small">
<!-- form markup omitted for brevity; see article body for full markup -->
</div>
</lightning-card>
</template>
import { LightningElement, wire, api } from 'lwc';
import createCase from '@salesforce/apex/CreateCaseController.createCase';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import { minimize, EnclosingUtilityId } from 'lightning/platformUtilityBarApi';
import { getRecord } from 'lightning/uiRecordApi';
const CONTACT_FIELDS = ['Contact.Name','Contact.Phone','Contact.AccountId'];
export default class CreateCaseUtility extends LightningElement {
contactName;
contactPhone;
accountId;
caseOrigin;
caseType;
description;
caseReason;
caseStatus;
subject;
@wire(EnclosingUtilityId) utilityId;
currentRecordId;
@api
set contactId(value) {
if (value !== this.currentRecordId) {
this.currentRecordId = value;
}
}
get contactId() {
return this.currentRecordId;
}
@wire(getRecord, { recordId: '$currentRecordId', fields: CONTACT_FIELDS })
wiredCase({ error, data }) {
if (data) {
this.contactName = data.fields.Name.value;
this.contactPhone = data.fields.Phone.value;
this.accountId = data.fields.AccountId.value;
} else if (error) {
console.error('Error fetching Contact:', error);
}
}
handleInputChange(event){
const field = event.target.dataset.field;
const value = event.target.value;
switch(field){
case 'CaseOrigin': this.caseOrigin = value; break;
case 'CaseType': this.caseType = value; break;
case 'Description': this.description = value; break;
case 'CaseReason': this.caseReason = value; break;
case 'CaseStatus': this.caseStatus = value; break;
case 'Subject': this.subject = value; break;
default: break;
}
}
async handleMinimize() {
try {
if (!this.utilityId) { return; }
const isMinimized = await minimize(this.utilityId);
console.log(`Minimize utility ${isMinimized ? 'successfully' : 'failed'}`);
} catch (error) {
console.error(error);
}
}
showToast(title, message, variant) {
this.dispatchEvent(new ShowToastEvent({ title, message, variant }));
}
validateCaseId() {
if (!this.currentRecordId || !this.currentRecordId.startsWith('003')) {
this.showToast('Case Create','Case should be created from Contact','error');
return false;
}
return true;
}
handleSave() {
if (!this.validateCaseId()) { return; }
const caseRecord = {
Type: this.caseType,
Status: this.caseStatus,
Origin: this.caseOrigin,
Description: this.description,
ContactId: this.currentRecordId,
Reason: this.caseReason,
AccountId: this.accountId,
ContactPhone: this.contactPhone,
Subject: this.subject
};
createCase({ cse: caseRecord })
.then(() => {
this.showToast('Success', 'Case created successfully!', 'success');
this.resetForm();
})
.catch((error) => {
this.showToast('Error', 'Error creating case: ' + (error?.body?.message || error.message), 'error');
});
}
}
Apex controller
Keep the server-side action minimal and secure. Validate any necessary fields in Apex if required by your security model.
public class CreateCaseController {
@AuraEnabled public static void createCase(Case cse){
insert cse;
}
}
Best practices and considerations
- Validate user permissions before inserting Cases in Apex if agents can only create specific case types.
- Consider adding server-side validation for required fields and record type assignment.
- Log errors and handle API exceptions gracefully in the UI.
- If PII searching (SSN, DOB) is used, ensure you follow your org’s compliance and masking policies.
Where this applies
Use this pattern in Service Console for support centers, contact centers, or any scenario where agents need to capture information quickly while multitasking or when record loads are delayed.
Conclusion
This utility-action pattern — Aura wrapper + LWC + lightweight Apex — helps call center agents capture case details faster, reduces data-loss risk, and improves accuracy by validating the Contact context before saving. For Salesforce admins and developers, it’s a pragmatic, low-complexity enhancement that delivers immediate productivity gains.
If you want the complete component files (full LWC template markup, CSS, and deployment notes), reply and I can include the full code bundle.








Leave a Reply