Typeahead means user types, debounced search fires, results appear. Common pattern.
LWC:
`javascript import { LightningElement } from 'lwc'; import searchAccounts from '@salesforce/apex/AccountSearchController.search';
export default class AccountTypeahead extends LightningElement { searchTerm = ''; results = []; timeout;
handleInput(event) { this.searchTerm = event.target.value; clearTimeout(this.timeout); this.timeout = setTimeout(() => this.doSearch(), 300); // debounce 300ms }
async doSearch() { if (this.searchTerm.length < 2) { this.results = []; return; } try { this.results = await searchAccounts({ term: this.searchTerm }); } catch (e) { console.error(e); } } } `
Apex:
apex public with sharing class AccountSearchController { @AuraEnabled(cacheable=false) public static List<Account> search(String term) { if (String.isBlank(term)) return new List<Account>(); String safe = '%' + String.escapeSingleQuotes(term) + '%'; return [SELECT Id, Name, Industry FROM Account WHERE Name LIKE :safe ORDER BY Name LIMIT 10]; } }
Key design decisions:
- Debounce (300ms) — don't fire on every keystroke; wait for typing pause.
- Min length (2 chars) — don't search single-letter terms.
- `cacheable=false` — search results change with input; can't be cached.
- `SOSL` for multi-object search — when typing should search Accounts, Contacts, Leads simultaneously, use SOSL.
- Result limit —
LIMIT 10for the dropdown; full results in a search-results page. - Escape input —
escapeSingleQuoteseven though we're using bind variables, because we're concatenating wildcards. - Loading indicator — show a spinner while waiting.
- Keyboard navigation — arrow keys to traverse results, Enter to select.
Performance: 300ms debounce + LIMIT 10 + indexed Name field = sub-100ms response in most orgs.
