### GraphQL Wire Adapter: Cursor-Based Pagination
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Implement cursor-based pagination using GraphQL `pageInfo.endCursor`, `hasNextPage`, and the `after` variable. This example paginates through Contact records.
```javascript
// graphqlPagination/graphqlPagination.js
import { LightningElement, wire } from 'lwc';
import { gql, graphql } from 'lightning/graphql';
const pageSize = 3;
export default class GraphqlPagination extends LightningElement {
after;
pageNumber = 1;
@wire(graphql, {
query: gql`
query paginatedContacts($after: String, $pageSize: Int!) {
uiapi {
query {
Contact(first: $pageSize after: $after orderBy: { Name: { order: ASC } }) {
edges { node { Id Name { value } } }
pageInfo { endCursor hasNextPage hasPreviousPage }
totalCount
}
}
}
}
`,
variables: '$variables'
})
contacts;
get variables() { return { after: this.after || null, pageSize }; }
get isLastPage() { return !this.contacts.data?.uiapi.query.Contact.pageInfo.hasNextPage; }
get totalPages() { return Math.ceil((this.contacts.data?.uiapi.query.Contact.totalCount || 0) / pageSize); }
handleNext() {
if (!this.isLastPage) {
this.after = this.contacts.data.uiapi.query.Contact.pageInfo.endCursor;
this.pageNumber++;
}
}
handleReset() { this.after = null; this.pageNumber = 1; }
}
```
--------------------------------
### Login to Salesforce CLI
Source: https://github.com/trailheadapps/lwc-recipes/blob/main/README.md
Logs into your hub org using Salesforce CLI and assigns it an alias. Ensure you have Salesforce CLI installed and your Dev Hub enabled.
```bash
sf org login web -d -a myhuborg
```
--------------------------------
### GraphQL Wire Adapter: Basic Query
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Query Salesforce records reactively using the `graphql` wire adapter and `gql` tagged template literals. This example fetches contacts with a picture, ordering them by name.
```javascript
// graphqlContacts/graphqlContacts.js
import { LightningElement, wire } from 'lwc';
import { gql, graphql } from 'lightning/graphql';
export default class GraphqlContacts extends LightningElement {
@wire(graphql, {
query: gql`
query getContacts {
uiapi {
query {
Contact(
where: { Picture__c: { ne: null } }
first: 5
orderBy: { Name: { order: ASC } }
) {
edges {
node {
Id
Name { value }
Phone { value }
Title { value }
Picture__c: Picture__c { value }
}
}
}
}
}
}
`
})
graphql;
get contacts() {
return this.graphql.data?.uiapi.query.Contact.edges.map((edge) => ({
Id: edge.node.Id,
Name: edge.node.Name.value,
Phone: edge.node.Phone.value,
Title: edge.node.Title.value,
Picture__c: edge.node.Picture__c.value
}));
}
}
```
--------------------------------
### Get Object Information with `getObjectInfo` Wire Adapter
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Fetch dynamic object metadata using the `getObjectInfo` wire adapter from `lightning/uiObjectInfoApi`. Provide the `objectApiName` to the adapter.
```javascript
// wireGetObjectInfo — dynamic object metadata
import { LightningElement, wire } from 'lwc';
import { getObjectInfo } from 'lightning/uiObjectInfoApi';
export default class WireGetObjectInfo extends LightningElement {
objectApiName;
@wire(getObjectInfo, { objectApiName: '$objectApiName' })
objectInfo;
handleBtnClick() {
this.objectApiName = this.template.querySelector('lightning-input').value;
}
}
```
--------------------------------
### Get List View Records with `getListUi` Wire Adapter
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Fetch records from a specific list view using the `getListUi` wire adapter. Specify `objectApiName`, `listViewApiName`, `sortBy`, and `pageSize`.
```javascript
// wireListView — records from a List View
import { getListUi } from 'lightning/uiListApi';
import CONTACT_OBJECT from '@salesforce/schema/Contact';
import NAME_FIELD from '@salesforce/schema/Contact.Name';
export default class WireListView extends LightningElement {
@wire(getListUi, {
objectApiName: CONTACT_OBJECT,
listViewApiName: 'All_Recipes_Contacts',
sortBy: NAME_FIELD,
pageSize: 10
})
listView;
get contacts() { return this.listView.data.records.records; }
}
```
--------------------------------
### Resolve Content Asset URLs with @salesforce/contentAssetUrl
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Use `@salesforce/contentAssetUrl` to get the CDN URL for content assets uploaded to Setup. This URL can be directly used in HTML attributes like `src`.
```javascript
import { LightningElement } from 'lwc';
import recipesLogo from '@salesforce/contentAssetUrl/recipes_sq_logo';
export default class MiscContentAsset extends LightningElement {
recipesLogoUrl = recipesLogo; // CDN URL — use directly in
}
```
--------------------------------
### Make External REST API Calls with fetch
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Use the native `fetch` API to call external REST APIs. Ensure the external host is added to CSP Trusted Sites in Salesforce Setup. Handles network errors and response parsing.
```javascript
import { LightningElement } from 'lwc';
const QUERY_URL = 'https://www.googleapis.com/books/v1/volumes?langRestrict=en&q=';
// PREREQUISITE: Add https://www.googleapis.com to CSP Trusted Sites in Setup
export default class MiscRestCall extends LightningElement {
books;
error;
isLoading = false;
searchKey = 'Harry Potter';
async handleSearchClick() {
this.isLoading = true;
try {
const response = await fetch(QUERY_URL + this.searchKey);
if (!response.ok) throw Error(response); // fetch doesn't throw on HTTP errors
this.books = await response.json();
this.error = undefined;
} catch (error) {
this.error = error;
this.books = undefined;
} finally {
this.isLoading = false;
}
}
}
```
--------------------------------
### Apply Styling Hooks to Lightning Input
Source: https://github.com/trailheadapps/lwc-recipes/blob/main/force-app/main/default/lwc/stylingHooks/stylingHooks.txt
Customize the appearance of a lightning-input component by overriding its specific styling hooks. This example targets border and accent container colors.
```css
lightning-input {
--slds-g-color-border-accent-1: var(--primary-color);
--slds-g-color-accent-container-1: var(--primary-color-alt-shade);
}
```
--------------------------------
### Record Picker — lightning-record-picker
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Use `lightning-record-picker` to let users search and select a Salesforce record. Handle the `onchange` event to get the selected `recordId` and use it to query further record details via GraphQL.
```APIDOC
## Record Picker — `lightning-record-picker`
Use `lightning-record-picker` to let users search and select a Salesforce record. Handle the `onchange` event to get the selected `recordId` and use it to query further record details via GraphQL.
```js
// recordPickerHello/recordPickerHello.js
import { wire, LightningElement } from 'lwc';
import { gql, graphql } from 'lightning/graphql';
export default class RecordPickerHello extends LightningElement {
selectedRecordId = '';
contact;
handleChange(event) {
this.selectedRecordId = event.detail.recordId; // populated by lightning-record-picker
}
get variables() { return { selectedRecordId: this.selectedRecordId }; }
@wire(graphql, {
query: gql`
query searchContacts($selectedRecordId: ID) {
uiapi {
query {
Contact(where: { Id: { eq: $selectedRecordId } } first: 1) {
edges { node { Id Name { value } Phone { value } Title { value } } }
}
}
}
}
`,
variables: '$variables'
})
wiredGraphQL({ data, errors }) {
if (!data) return;
const results = data.uiapi.query.Contact.edges.map((edge) => ({
Id: edge.node.Id, Name: edge.node.Name.value, Phone: edge.node.Phone.value, Title: edge.node.Title.value
}));
this.contact = results?.[0];
}
}
```
```
--------------------------------
### Get Current Page Reference with `CurrentPageReference`
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Obtain the current page's reference object, including its type, attributes, and state, using the `CurrentPageReference` wire adapter.
```javascript
// wireCurrentPageReference/wireCurrentPageReference.js
import { LightningElement, wire } from 'lwc';
import { CurrentPageReference } from 'lightning/navigation';
export default class WireCurrentPageReference extends LightningElement {
@wire(CurrentPageReference) pageRef;
get currentPageReference() {
return this.pageRef ? JSON.stringify(this.pageRef, null, 2) : '';
}
}
// pageRef shape: { type: 'standard__recordPage', attributes: { recordId, ... }, state: { ... } }
```
--------------------------------
### Child to Parent Communication via Custom Events
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
A child component dispatches a `CustomEvent`, and the parent component listens for it using the `on` attribute in its template. This example shows basic 'previous' and 'next' event handling.
```javascript
// paginator/paginator.js (child)
import { LightningElement } from 'lwc';
export default class Paginator extends LightningElement {
handlePrevious() { this.dispatchEvent(new CustomEvent('previous')); }
handleNext() { this.dispatchEvent(new CustomEvent('next')); }
}
// ---
// eventSimple/eventSimple.js (parent)
import { LightningElement } from 'lwc';
export default class EventSimple extends LightningElement {
page = 1;
handlePrevious() { if (this.page > 1) this.page--; }
handleNext() { this.page++; }
}
```
```html
```
--------------------------------
### GraphQL Wire Adapter: Reactive Variables
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Make GraphQL query variables reactive by using a `variables` getter. LWC re-evaluates the getter and re-executes the query when referenced component properties change. This example searches for contacts based on a search key.
```javascript
// graphqlVariables/graphqlVariables.js
import { LightningElement, wire } from 'lwc';
import { gql, graphql } from 'lightning/graphql';
const DELAY = 300;
export default class GraphqlVariables extends LightningElement {
searchKey = '';
@wire(graphql, {
query: gql`
query searchContacts($searchKey: String!, $limit: Int = 5) {
uiapi {
query {
Contact(where: { Name: { like: $searchKey } } first: $limit orderBy: { Name: { order: ASC } }) {
edges { node { Id Name { value } } }
}
}
}
}
`,
variables: '$variables' // points to the getter below
})
contacts;
get variables() {
// Getter is re-evaluated whenever this.searchKey changes
return { searchKey: this.searchKey === '' ? '%' : `%${this.searchKey}%` };
}
handleKeyChange(event) {
window.clearTimeout(this.delayTimeout);
const searchKey = event.target.value;
// eslint-disable-next-line @lwc/lwc/no-async-operation
this.delayTimeout = setTimeout(() => { this.searchKey = searchKey; }, DELAY);
}
}
```
--------------------------------
### Import Sample Data
Source: https://github.com/trailheadapps/lwc-recipes/blob/main/README.md
Imports sample data into the scratch org using a data plan JSON file. This populates the org with necessary data for the recipes.
```bash
sf data tree import -p ./data/data-plan.json
```
--------------------------------
### Deploy App to Scratch Org
Source: https://github.com/trailheadapps/lwc-recipes/blob/main/README.md
Deploys the LWC recipes application to the created scratch org. This command pushes the project source to the org.
```bash
sf project deploy start
```
--------------------------------
### Run Linting and Formatting Commands
Source: https://github.com/trailheadapps/lwc-recipes/blob/main/README.md
Execute these commands from the project's root folder to manually run Prettier and ESLint for code formatting and linting. Check the package.json file for a complete list of available commands.
```bash
npm run lint
```
```bash
npm run prettier
```
--------------------------------
### Open Scratch Org
Source: https://github.com/trailheadapps/lwc-recipes/blob/main/README.md
Opens the newly created scratch org in your default web browser. This allows you to interact with the deployed application.
```bash
sf org open
```
--------------------------------
### Create Scratch Org
Source: https://github.com/trailheadapps/lwc-recipes/blob/main/README.md
Creates a new scratch org with a specified definition file and assigns it an alias. This command requires the Salesforce CLI and a configured Dev Hub.
```bash
sf org create scratch -d -f config/project-scratch-def.json -a lwc-recipes
```
--------------------------------
### Get Picklist Field Values with `getPicklistValues`
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Retrieve picklist field values for a specific record type using the `getPicklistValues` wire adapter. Requires `recordTypeId` and `fieldApiName`.
```javascript
// wireGetPicklistValues — picklist field values for a record type
import { getPicklistValues } from 'lightning/uiObjectInfoApi';
import TYPE_FIELD from '@salesforce/schema/Account.Type';
export default class WireGetPicklistValues extends LightningElement {
@wire(getPicklistValues, { recordTypeId: '012000000000000AAA', fieldApiName: TYPE_FIELD })
picklistValues;
}
```
--------------------------------
### Open Org using CLI
Source: https://github.com/trailheadapps/lwc-recipes/blob/main/README.md
Open your authorized Salesforce org in a web browser using the Salesforce CLI.
```bash
sf org open -o mydevorg
```
--------------------------------
### Deploy LWC Recipes App using CLI
Source: https://github.com/trailheadapps/lwc-recipes/blob/main/README.md
Deploy the LWC Recipes application to your authorized Salesforce org using the Salesforce CLI.
```bash
sf project deploy start -d force-app
```
--------------------------------
### Login to Salesforce Org using CLI
Source: https://github.com/trailheadapps/lwc-recipes/blob/main/README.md
Authorize your Trailhead Playground or Developer Edition org using the Salesforce CLI and assign it an alias for easier reference.
```bash
sf org login web -s -a mydevorg
```
--------------------------------
### Clone LWC Recipes Repository
Source: https://github.com/trailheadapps/lwc-recipes/blob/main/README.md
Clones the lwc-recipes repository from GitHub and navigates into the project directory. This is a prerequisite for deploying the app.
```bash
git clone https://github.com/trailheadapps/lwc-recipes
cd lwc-recipes
```
--------------------------------
### Get Current User ID with @salesforce/user/Id
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Import the running user's Salesforce ID as a compile-time constant using `@salesforce/user/Id`. This provides the 18-character Salesforce User ID of the current user.
```javascript
// miscGetUserId/miscGetUserId.js
import { LightningElement } from 'lwc';
import Id from '@salesforce/user/Id';
export default class MiscGetUserId extends LightningElement {
userId = Id; // the 18-character Salesforce User ID of the current user
}
```
--------------------------------
### NavigationMixin - Navigate to Object, List View, Tab
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Demonstrates various NavigationMixin.Navigate page reference types for navigating to object creation, list views, and custom tabs.
```javascript
// Navigate to Create New Contact modal
this[NavigationMixin.Navigate]({
type: 'standard__objectPage',
attributes: { objectApiName: 'Contact', actionName: 'new' }
});
// Navigate to a List View (with filter state)
this[NavigationMixin.Navigate]({
type: 'standard__objectPage',
attributes: { objectApiName: 'Contact', actionName: 'list' },
state: { filterName: 'Recent' }
});
// Navigate to a custom tab/nav item
this[NavigationMixin.Navigate}({
type: 'standard__navItemPage',
attributes: { apiName: 'Hello' }
});
```
--------------------------------
### Trigger Data Refresh After Mutation
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Dispatch a RefreshEvent from lightning/refresh after a successful DML operation to notify the page container and related components to refresh their data. This example also shows how to display a success toast and reset input fields.
```javascript
// dispatchRefreshEvent/dispatchRefreshEvent.js
import { LightningElement } from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import { RefreshEvent } from 'lightning/refresh';
export default class DispatchRefreshEvent extends LightningElement {
handleSuccess(event) {
this.dispatchEvent(new ShowToastEvent({
title: 'Account created',
message: 'Record ID: ' + event.detail.id,
variant: 'success'
}));
this.dispatchEvent(new RefreshEvent()); // triggers page-level data refresh
this.template.querySelectorAll('lightning-input-field').forEach((field) => field.reset());
}
}
```
--------------------------------
### LDS `createRecord`
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Create a new Salesforce record programmatically without navigating away from the current page using `createRecord`.
```APIDOC
## LDS — `createRecord`
Create a new Salesforce record programmatically without navigating away from the current page. Uses schema tokens for type safety and `ShowToastEvent` to give user feedback.
```js
// ldsCreateRecord/ldsCreateRecord.js
import { LightningElement } from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import { createRecord } from 'lightning/uiRecordApi';
import { reduceErrors } from 'c/ldsUtils';
import ACCOUNT_OBJECT from '@salesforce/schema/Account';
import NAME_FIELD from '@salesforce/schema/Account.Name';
export default class LdsCreateRecord extends LightningElement {
accountId;
name = '';
handleNameChange(event) {
this.accountId = undefined;
this.name = event.target.value;
}
async createAccount() {
const fields = {};
fields[NAME_FIELD.fieldApiName] = this.name;
const recordInput = { apiName: ACCOUNT_OBJECT.objectApiName, fields };
try {
const account = await createRecord(recordInput);
this.accountId = account.id;
this.dispatchEvent(new ShowToastEvent({ title: 'Success', message: 'Account created', variant: 'success' }));
} catch (error) {
this.dispatchEvent(new ShowToastEvent({ title: 'Error creating record', message: reduceErrors(error).join(', '), variant: 'error' }));
}
}
}
```
```
--------------------------------
### Iterator Directive for First/Last Item Detection
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Use the iterator directive when special logic or styling is needed for the first or last item in a rendered list. This example uses lwc:if to conditionally apply classes to the first and last list items.
```html
-
{it.value.Name}, {it.value.Title}
```
--------------------------------
### Create Record with Server-Side Defaults
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Retrieve server-side create defaults and generate a record input object filtered to only creatable fields. Use this input directly with `createRecord`.
```javascript
// ldsGenerateRecordInputForCreate/ldsGenerateRecordInputForCreate.js
import { LightningElement, wire } from 'lwc';
import { createRecord, getRecordCreateDefaults, generateRecordInputForCreate } from 'lightning/uiRecordApi';
import ACCOUNT_OBJECT from '@salesforce/schema/Account';
import NAME_FIELD from '@salesforce/schema/Account.Name';
import AREANUMBER_FIELD from '@salesforce/schema/Account.AreaNumber__c';
export default class LdsGenerateRecordInputForCreate extends LightningElement {
recordInput;
@wire(getRecordCreateDefaults, { objectApiName: ACCOUNT_OBJECT })
loadAccountCreateDefaults({ data, error }) {
if (data) {
this.recordInput = generateRecordInputForCreate(
data.record,
data.objectInfos[ACCOUNT_OBJECT.objectApiName] // filters to creatable fields only
);
}
}
handleFieldChange(event) {
this.recordInput.fields[event.target.dataset.fieldName] = event.target.value;
}
async createAccount() {
const account = await createRecord(this.recordInput);
// account.id contains the new record's ID
}
}
```
--------------------------------
### Reactive State Management with `@lwc/state`
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Define a shared reactive state store using `defineState`. Components consume this state with `fromContext`, and the component tree must be wrapped in a `` context provider.
```javascript
// opportunitiesStateManager/opportunitiesStateManager.js (state definition)
import { defineState } from '@lwc/state';
export default defineState(({ atom, computed, setAtom }) => {
const opportunities = atom([]); // mutable reactive atom
const setOpportunities = (newOpportunities) => setAtom(opportunities, newOpportunities);
const totalAmount = computed([opportunities], (oppties) =>
oppties.reduce((total, oppty) => total + oppty.Amount.value, 0)
);
return { opportunities, setOpportunities, totalAmount };
});
```
```javascript
// opportunitiesList/opportunitiesList.js (consumer — reads from state)
import { LightningElement } from 'lwc';
import { fromContext } from '@lwc/state';
import opportunitiesStateManager from 'c/opportunitiesStateManager';
export default class OpportunitiesList extends LightningElement {
stateManager = fromContext(opportunitiesStateManager); // subscribes to shared state
get data() {
return this.stateManager.value.opportunities.map((oppty) => ({
id: oppty.Id, name: oppty.Name.value, stage: oppty.StageName.value, amount: oppty.Amount.value
}));
}
}
```
```javascript
// stateManager/stateManager.js (root — creates state context and writes to it)
import { LightningElement, wire } from 'lwc';
import { default as opportunitiesStateManager } from 'c/opportunitiesStateManager';
import {gql, graphql} from 'lightning/graphql';
export default class StateManager extends LightningElement {
state = opportunitiesStateManager(); // creates the state instance
@wire(graphql, { query:gql`...`, variables: '$queryVariables' })
wiredOpportunities({ data }) {
this.state.value.setOpportunities(
(data?.uiapi?.query?.Opportunity?.edges || []).map((edge) => edge.node)
);
}
}
```
--------------------------------
### Assign Permission Set
Source: https://github.com/trailheadapps/lwc-recipes/blob/main/README.md
Assigns the 'recipes' permission set to the default user in the scratch org. This is necessary to access the application's features.
```bash
sf org assign permset -n recipes
```
--------------------------------
### Select Salesforce Records with lightning-record-picker
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Use `lightning-record-picker` to allow users to search and select Salesforce records. Handle the `onchange` event to retrieve the selected `recordId` for further data querying.
```javascript
//recordPickerHello/recordPickerHello.js
import { wire, LightningElement } from 'lwc';
import { gql, graphql } from 'lightning/graphql';
export default class RecordPickerHello extends LightningElement {
selectedRecordId = '';
contact;
handleChange(event) {
this.selectedRecordId = event.detail.recordId; // populated by lightning-record-picker
}
get variables() { return { selectedRecordId: this.selectedRecordId }; }
@wire(graphql, {
query: gql`
query searchContacts($selectedRecordId: ID) {
uiapi {
query {
Contact(where: { Id: { eq: $selectedRecordId } } first: 1) {
edges { node { Id Name { value } Phone { value } Title { value } } }
}
}
}
}
`,
variables: '$variables'
})
wiredGraphQL({ data, errors }) {
if (!data) return;
const results = data.uiapi.query.Contact.edges.map((edge) => ({
Id: edge.node.Id, Name: edge.node.Name.value, Phone: edge.node.Phone.value, Title: edge.node.Title.value
}));
this.contact = results?.[0];
}
}
```
--------------------------------
### Resolve Static Resource URLs with @salesforce/resourceUrl
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Import static resources to resolve their URLs. Use the imported variable directly for root files or append paths for files within ZIP archives.
```javascript
import { LightningElement } from 'lwc';
import trailheadLogo from '@salesforce/resourceUrl/trailhead_logo';
import trailheadCharacters from '@salesforce/resourceUrl/trailhead_characters';
export default class MiscStaticResource extends LightningElement {
trailheadLogoUrl = trailheadLogo; // root file URL
einsteinUrl = trailheadCharacters + '/images/einstein.png'; // path within a ZIP archive
}
```
--------------------------------
### Create Record with LDS createRecord
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Creates a new Salesforce record programmatically without navigating away from the current page. Uses schema tokens for type safety and ShowToastEvent for user feedback.
```javascript
import { LightningElement } from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import { createRecord } from 'lightning/uiRecordApi';
import { reduceErrors } from 'c/ldsUtils';
import ACCOUNT_OBJECT from '@salesforce/schema/Account';
import NAME_FIELD from '@salesforce/schema/Account.Name';
export default class LdsCreateRecord extends LightningElement {
accountId;
name = '';
handleNameChange(event) {
this.accountId = undefined;
this.name = event.target.value;
}
async createAccount() {
const fields = {};
fields[NAME_FIELD.fieldApiName] = this.name;
const recordInput = { apiName: ACCOUNT_OBJECT.objectApiName, fields };
try {
const account = await createRecord(recordInput);
this.accountId = account.id;
this.dispatchEvent(new ShowToastEvent({ title: 'Success', message: 'Account created', variant: 'success' }));
} catch (error) {
this.dispatchEvent(new ShowToastEvent({ title: 'Error creating record', message: reduceErrors(error).join(', '), variant: 'error' }));
}
}
}
```
--------------------------------
### Manage Console Tabs with Workspace API
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Use functions from `lightning/platformWorkspaceApi` to open, focus, close, and label tabs in Salesforce Console applications. Always check `IsConsoleNavigation` before attempting to use these functions.
```javascript
// workspaceAPIOpenTab/workspaceAPIOpenTab.js
import { LightningElement, wire } from 'lwc';
import { IsConsoleNavigation, openTab } from 'lightning/platformWorkspaceApi';
export default class WorkspaceAPIOpenTab extends LightningElement {
@wire(IsConsoleNavigation) isConsoleNavigation; // false in standard navigation
async openTab() {
if (!this.isConsoleNavigation) return; // only valid in console apps
await openTab({
pageReference: {
type: 'standard__objectPage',
attributes: { objectApiName: 'Contact', actionName: 'list' }
},
focus: true,
label: 'Contacts List'
});
}
}
```
--------------------------------
### Use Async Notification Modals
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Utilize LightningAlert, LightningConfirm, and LightningPrompt for asynchronous modal dialogs that return Promises. These modules allow for user interaction through alerts, confirmations, and prompts.
```javascript
// miscNotificationModules/miscNotificationModules.js
import { LightningElement } from 'lwc';
import LightningAlert from 'lightning/alert';
import LightningConfirm from 'lightning/confirm';
import LightningPrompt from 'lightning/prompt';
export default class MiscNotificationModules extends LightningElement {
async handleAlertClick() {
await LightningAlert.open({ message: 'This is an alert', theme: 'info', label: 'Alert!' });
}
async handleConfirmClick() {
const result = await LightningConfirm.open({
message: 'Are you sure?', variant: 'headerless', label: 'Confirm action'
});
// result === true (OK) or false (Cancel)
}
async handlePromptClick() {
const value = await LightningPrompt.open({
message: 'Enter a value', label: 'Please Respond', defaultValue: 'initial', theme: 'shade'
});
// value === string (OK clicked) or null (Cancel clicked)
}
}
```
--------------------------------
### Execute GraphQL Mutation with executeMutation
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Use the `executeMutation` function to create, update, or delete records with a `gql` mutation string. Ensure the `lightning/graphql` module is imported.
```javascript
//graphqlMutationCreate/graphqlMutationCreate.js
import { LightningElement } from 'lwc';
import { gql, executeMutation } from 'lightning/graphql';
export default class GraphqlMutationCreate extends LightningElement {
accountName = '';
accountId;
errors;
isLoading = false;
getCreateQuery(name) {
return gql`
mutation CreateAccount {
uiapi {
AccountCreate(input: { Account: { Name: "${name}" } }) {
Record { Id Name { value } }
}
}
}
`;
}
async handleCreateAccount() {
if (!this.accountName) { this.errors = ['Account Name is required']; return; }
this.isLoading = true;
try {
const result = await executeMutation({ query: this.getCreateQuery(this.accountName) });
if (result.errors) {
this.errors = result.errors;
} else {
this.accountId = result.data.uiapi.AccountCreate.Record.Id;
}
} catch (error) {
this.errors = error;
} finally {
this.isLoading = false;
}
}
}
```
--------------------------------
### Render Record Forms with lightning-record-form
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Use `lightning-record-form` to display records in view, edit, or create mode with minimal code. Provide a `record-id` for existing records or omit it for new record creation.
```javascript
//recordFormStaticContact/recordFormStaticContact.js
import { LightningElement, api } from 'lwc';
import ACCOUNT_FIELD from '@salesforce/schema/Contact.AccountId';
import NAME_FIELD from '@salesforce/schema/Contact.Name';
import TITLE_FIELD from '@salesforce/schema/Contact.Title';
import PHONE_FIELD from '@salesforce/schema/Contact.Phone';
import EMAIL_FIELD from '@salesforce/schema/Contact.Email';
export default class RecordFormStaticContact extends LightningElement {
@api recordId; // provided by the Lightning page
@api objectApiName;
fields = [ACCOUNT_FIELD, NAME_FIELD, TITLE_FIELD, PHONE_FIELD, EMAIL_FIELD];
}
```
```html
```
--------------------------------
### Multiple Templates with render() Hook
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Implement the render() lifecycle hook to dynamically switch between different HTML template modules at runtime. This is useful for components that need to display different layouts based on certain conditions.
```javascript
// miscMultipleTemplates/miscMultipleTemplates.js
import { LightningElement } from 'lwc';
import templateOne from './templateOne.html';
import templateTwo from './templateTwo.html';
export default class MiscMultipleTemplates extends LightningElement {
showTemplateOne = true;
render() {
return this.showTemplateOne ? templateOne : templateTwo;
}
switchTemplate() {
this.showTemplateOne = !this.showTemplateOne;
}
}
```
--------------------------------
### Format Dates and Numbers with @salesforce/i18n
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Import locale and currency tokens from `@salesforce/i18n` to format dates and numbers according to the current user's locale settings. This ensures proper internationalization of your component's output.
```javascript
// miscI18n/miscI18n.js
import { LightningElement } from 'lwc';
import USER_LOCALE from '@salesforce/i18n/locale';
import USER_CURRENCY from '@salesforce/i18n/currency';
export default class I18n extends LightningElement {
userLocale = USER_LOCALE; // e.g., 'en-US'
userCurrency = USER_CURRENCY; // e.g., 'USD'
get dateUserLocale() {
return new Intl.DateTimeFormat(USER_LOCALE).format(new Date());
}
get currencyUserLocale() {
return new Intl.NumberFormat(USER_LOCALE, {
style: 'currency', currency: USER_CURRENCY, currencyDisplay: 'symbol'
}).format(100);
}
}
```
--------------------------------
### NavigationMixin - Navigate to Record View/Edit
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Mixes NavigationMixin into a component and uses this[NavigationMixin.Navigate] to navigate to a record's view or edit page.
```javascript
// navToRecord/navToRecord.js
import { LightningElement, wire } from 'lwc';
import { NavigationMixin } from 'lightning/navigation';
import getSingleContact from '@salesforce/apex/ContactController.getSingleContact';
export default class NavToRecord extends NavigationMixin(LightningElement) {
@wire(getSingleContact) contact;
// Navigate to a record's view page
navigateToContact() {
this[NavigationMixin.Navigate]({
type: 'standard__recordPage',
attributes: { recordId: this.contact.data.Id, objectApiName: 'Contact', actionName: 'view' }
});
}
// Navigate to the record's edit modal
navigateToEdit() {
this[NavigationMixin.Navigate]({
type: 'standard__recordPage',
attributes: { recordId: this.contact.data.Id, objectApiName: 'Contact', actionName: 'edit' }
});
}
}
```
--------------------------------
### Open Custom Modal with LightningModal
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Extend LightningModal to create custom modals. Open them from a parent component using `MyModal.open({...})`. The return value from `this.close()` is available via an await expression in the caller.
```javascript
// myModal/myModal.js (modal component)
import { api } from 'lwc';
import LightningModal from 'lightning/modal';
export default class MyModal extends LightningModal {
@api header;
@api content;
handleClose() {
this.close('return value'); // value is returned to the caller's await expression
}
}
```
```javascript
// miscModal/miscModal.js (caller)
import { LightningElement } from 'lwc';
import MyModal from 'c/myModal';
export default class MiscModal extends LightningElement {
async handleShowModal() {
const result = await MyModal.open({
size: 'small',
description: 'Accessible description',
header: 'The modal header',
content: 'The modal content'
});
// result === 'return value' if closed via custom button, or undefined if closed via X
}
}
```
--------------------------------
### LMS Publisher Component
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Publishes a message to a named Message Channel. Requires importing MessageContext and the specific channel.
```javascript
// lmsPublisherWebComponent/lmsPublisherWebComponent.js
import { LightningElement, wire } from 'lwc';
import { publish, MessageContext } from 'lightning/messageService';
import RECORD_SELECTED_CHANNEL from '@salesforce/messageChannel/Record_Selected__c';
import getContactList from '@salesforce/apex/ContactController.getContactList';
export default class LmsPublisherWebComponent extends LightningElement {
@wire(getContactList) contacts;
@wire(MessageContext)
messageContext;
handleContactSelect(event) {
const payload = { recordId: event.target.contact.Id };
publish(this.messageContext, RECORD_SELECTED_CHANNEL, payload);
}
}
```
--------------------------------
### Structured Logging with `lightning/logger`
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Use the `log()` function from `lightning/logger` to send structured event monitoring messages that integrate with Salesforce Event Monitoring. Use `console.log` for browser console messages only.
```javascript
// miscLogger/miscLogger.js
import { LightningElement } from 'lwc';
import { log } from 'lightning/logger';
export default class MiscLogger extends LightningElement {
logMessageEventMonitoring() {
log({ type: 'click', action: 'Log' }); // captured by Salesforce Event Monitoring
}
logMessageConsole() {
console.log('This message is logged to the browser console only');
}
}
```
--------------------------------
### Fetch Record with LDS getRecord Wire Adapter
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Fetches a record and specific fields from the Lightning Data Service cache. Uses schema token imports to prevent hard-coded API name strings.
```javascript
import { LightningElement, wire } from 'lwc';
import { getRecord } from 'lightning/uiRecordApi';
import NAME_FIELD from '@salesforce/schema/User.Name';
import EMAIL_FIELD from '@salesforce/schema/User.Email';
import Id from '@salesforce/user/Id';
export default class WireGetRecord extends LightningElement {
userId = Id;
@wire(getRecord, {
recordId: '$userId',
fields: [NAME_FIELD],
optionalFields: [EMAIL_FIELD] // returned if accessible, never causes an error if absent
})
record;
get recordStr() {
return this.record ? JSON.stringify(this.record.data, null, 2) : '';
}
}
```
--------------------------------
### Query Shadow DOM Elements with querySelectorAll
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Query the shadow DOM for elements or child components using `this.template.querySelector(All)`. Use `querySelectorAll` combined with `Array.from` to efficiently work with multiple matched elements.
```javascript
// miscDomQuery/miscDomQuery.js
import { LightningElement } from 'lwc';
export default class MiscDomQuery extends LightningElement {
selection;
handleCheckboxChange() {
const checked = Array.from(this.template.querySelectorAll('lightning-input'))
.filter((element) => element.checked)
.map((element) => element.label);
this.selection = checked.join(', ');
}
}
```
--------------------------------
### Normalize LDS, Apex, or Network Errors
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Use the `reduceErrors` utility to normalize various error shapes into a string array of human-readable messages. Import it from `c/ldsUtils`.
```javascript
// ldsUtils/ldsUtils.js
export function reduceErrors(errors) {
if (!Array.isArray(errors)) errors = [errors];
return errors
.filter((error) => !!error)
.map((error) => {
if (Array.isArray(error.body)) return error.body.map((e) => e.message);
if (error?.body?.pageErrors?.length > 0) return error.body.pageErrors.map((e) => e.message);
if (error?.body?.fieldErrors && Object.keys(error.body.fieldErrors).length > 0) {
const fieldErrors = [];
Object.values(error.body.fieldErrors).forEach((arr) => fieldErrors.push(...arr.map((e) => e.message)));
return fieldErrors;
}
if (error?.body?.output?.errors?.length > 0) return error.body.output.errors.map((e) => e.message);
if (error?.body?.output?.fieldErrors) { /* ... same pattern ... */ }
if (error.body && typeof error.body.message === 'string') return error.body.message;
if (typeof error.message === 'string') return error.message;
return error.statusText;
})
.reduce((prev, curr) => prev.concat(curr), [])
.filter((message) => !!message);
}
// Usage
import { reduceErrors } from 'c/ldsUtils';
// ...
message: reduceErrors(error).join(', ')
```
--------------------------------
### Show Platform-Native Toast Notifications
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Dispatch a ShowToastEvent to display platform-native toast messages. Supported variants include 'success', 'error', 'warning', and 'info'.
```javascript
// miscToastNotification/miscToastNotification.js
import { LightningElement } from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
export default class MiscToastNotification extends LightningElement {
showNotification() {
this.dispatchEvent(new ShowToastEvent({
title: 'Sample Title',
message: 'Sample Message',
variant: 'success' // 'success' | 'error' | 'warning' | 'info'
}));
}
}
```
--------------------------------
### Apex Imperative Call with Parameters
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Pass an object as the sole argument to an Apex method that requires parameters. Ensure that the key names in the object exactly match the Apex method's parameter names.
```javascript
// apexImperativeMethodWithParams/apexImperativeMethodWithParams.js
import { LightningElement } from 'lwc';
import findContacts from '@salesforce/apex/ContactController.findContacts';
export default class ApexImperativeMethodWithParams extends LightningElement {
searchKey = '';
contacts;
error;
handleKeyChange(event) {
this.searchKey = event.target.value;
}
async handleSearch() {
try {
this.contacts = await findContacts({ searchKey: this.searchKey });
this.error = undefined;
} catch (error) {
this.error = error;
this.contacts = undefined;
}
}
}
```
--------------------------------
### Apex Contact Controller for LWC
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Server-side Apex controller exposing cacheable read methods and DML operations. Use for data retrieval and manipulation from LWC.
```apex
public with sharing class ContactController {
@AuraEnabled(cacheable=true)
public static List getContactList() {
return [
SELECT Id, Name, FirstName, LastName, Title, Phone, Email, Picture__c
FROM Contact WHERE Picture__c != NULL WITH USER_MODE LIMIT 10
];
}
@AuraEnabled(cacheable=true)
public static List findContacts(String searchKey) {
String key = '%' + searchKey + '%';
return [
SELECT Id, Name, Title, Phone, Email, Picture__c
FROM Contact WHERE Name LIKE :key AND Picture__c != NULL WITH USER_MODE LIMIT 10
];
}
@AuraEnabled(cacheable=true)
public static Contact getSingleContact() {
return [SELECT Id, Name, Title, Phone, Email, Picture__c FROM Contact WITH USER_MODE LIMIT 1];
}
@AuraEnabled
public static void updateContacts(List contactsForUpdate) {
if (!Schema.sObjectType.Contact.isUpdateable()) {
throw new SecurityException('Insufficient permissions to update contacts');
}
update contactsForUpdate;
}
@AuraEnabled
public static void updateContact(Id recordId, String firstName, String lastName) {
Contact contact = new Contact(Id = recordId, FirstName = firstName, LastName = lastName);
update contact;
}
}
```
--------------------------------
### ContactController Apex Class
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Server-side Apex controller exposing cacheable read methods and DML operations used by the recipe components.
```APIDOC
## Apex — ContactController (Apex Class)
Server-side Apex controller exposing cacheable read methods and DML operations used by the recipe components.
```apex
// classes/ContactController.cls
public with sharing class ContactController {
@AuraEnabled(cacheable=true)
public static List getContactList() {
return [
SELECT Id, Name, FirstName, LastName, Title, Phone, Email, Picture__c
FROM Contact WHERE Picture__c != NULL WITH USER_MODE LIMIT 10
];
}
@AuraEnabled(cacheable=true)
public static List findContacts(String searchKey) {
String key = '%' + searchKey + '%';
return [
SELECT Id, Name, Title, Phone, Email, Picture__c
FROM Contact WHERE Name LIKE :key AND Picture__c != NULL WITH USER_MODE LIMIT 10
];
}
@AuraEnabled(cacheable=true)
public static Contact getSingleContact() {
return [SELECT Id, Name, Title, Phone, Email, Picture__c FROM Contact WITH USER_MODE LIMIT 1];
}
@AuraEnabled
public static void updateContacts(List contactsForUpdate) {
if (!Schema.sObjectType.Contact.isUpdateable()) {
throw new SecurityException('Insufficient permissions to update contacts');
}
update contactsForUpdate;
}
@AuraEnabled
public static void updateContact(Id recordId, String firstName, String lastName) {
Contact contact = new Contact(Id = recordId, FirstName = firstName, LastName = lastName);
update contact;
}
}
```
```
--------------------------------
### LDS `getRecord` Wire Adapter
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Fetch a record and specific fields from the Lightning Data Service cache using the `getRecord` wire adapter.
```APIDOC
## LDS — `getRecord` Wire Adapter
Fetch a record and specific fields from the Lightning Data Service cache. Schema token imports prevent hard-coded API name strings.
```js
// wireGetRecord/wireGetRecord.js
import { LightningElement, wire } from 'lwc';
import { getRecord } from 'lightning/uiRecordApi';
import NAME_FIELD from '@salesforce/schema/User.Name';
import EMAIL_FIELD from '@salesforce/schema/User.Email';
import Id from '@salesforce/user/Id';
export default class WireGetRecord extends LightningElement {
userId = Id;
@wire(getRecord, {
recordId: '$userId',
fields: [NAME_FIELD],
optionalFields: [EMAIL_FIELD] // returned if accessible, never causes an error if absent
})
record;
get recordStr() {
return this.record ? JSON.stringify(this.record.data, null, 2) : '';
}
}
```
```
--------------------------------
### Apex @wire with Reactive Parameters
Source: https://context7.com/trailheadapps/lwc-recipes/llms.txt
Use a reactive property prefixed with '$' to automatically re-invoke an Apex wire call when the property changes. A debounce timer is included to prevent excessive server calls.
```javascript
// apexWireMethodWithParams/apexWireMethodWithParams.js
import { LightningElement, wire } from 'lwc';
import findContacts from '@salesforce/apex/ContactController.findContacts';
const DELAY = 300;
export default class ApexWireMethodWithParams extends LightningElement {
searchKey = '';
// '$searchKey' — the $ prefix makes this parameter reactive
@wire(findContacts, { searchKey: '$searchKey' })
contacts;
handleKeyChange(event) {
window.clearTimeout(this.delayTimeout);
const searchKey = event.target.value;
// eslint-disable-next-line @lwc/lwc/no-async-operation
this.delayTimeout = setTimeout(() => {
this.searchKey = searchKey; // triggers @wire re-execution
}, DELAY);
}
}
```