Skip to main content

How to Implement Dynamic Autofill and Auto-Suggest in Salesforce LWC

In plain words: Autofill in Lightning Web Components (LWC) automatically predicts, completes, or populates related form inputs as the user types. This is typically done either by filtering client-side suggestions or by fetching live record details with Lightning Data Service (getRecord) to populate secondary fields instantly.

Manually entering repetitive data slows down business users and increases data entry errors. Implementing smart autofill functionality provides a streamlined, desktop-grade experience. Depending on your use case, you can implement instant keyword-based auto-completion or automatic field population from linked Salesforce records.

Prerequisites

  • A Salesforce Developer Edition, Sandbox, or Scratch Org.
  • Salesforce CLI (sf) installed and authenticated.
  • Basic understanding of LWC reactivity, events (onchange), and wire adapters (uiRecordApi).

Pattern 1: Real-Time Search & Autocomplete Suggestions

This pattern monitors user keystrokes in a search input and automatically matches the entry against a predefined list or API response to complete the input.

HTML Template (autoSuggestSearch.html):

<template>
    <lightning-card title="Instant Keyword Auto-Suggest" icon-name="utility:search">
        <div class="slds-p-around_medium">
            <lightning-input
                type="search"
                label="Search Products or Categories"
                placeholder="Type 'app', 'clo', or 'ser'..."
                value={searchTerm}
                onchange={handleSearchChange}
                autocomplete="off">
            </lightning-input>

            <template lwc:if={matchedSuggestion}>
                <div class="slds-box slds-theme_shade slds-m-top_small">
                    <p class="slds-text-body_small">
                        Suggested match: <strong class="slds-text-color_success">{matchedSuggestion}</strong>
                    </p>
                    <lightning-button 
                        class="slds-m-top_xx-small"
                        variant="base" 
                        label="Apply Suggestion" 
                        onclick={applySuggestion}>
                    </lightning-button>
                </div>
            </template>
        </div>
    </lightning-card>
</template>

JavaScript Controller (autoSuggestSearch.js):

import { LightningElement } from 'lwc';

const SUGGESTIONS_POOL = [
    'Apparel & Accessories',
    'Application Integration Services',
    'Cloud Database Storage',
    'Cloud Security Gateway',
    'Serverless Compute Engine'
];

export default class AutoSuggestSearch extends LightningElement {
    searchTerm = '';
    matchedSuggestion = '';

    handleSearchChange(event) {
        this.searchTerm = event.target.value;

        if (this.searchTerm && this.searchTerm.trim().length >= 2) {
            const normalizedQuery = this.searchTerm.toLowerCase();
            const found = SUGGESTIONS_POOL.find(item =>
                item.toLowerCase().includes(normalizedQuery)
            );
            this.matchedSuggestion = found || '';
        } else {
            this.matchedSuggestion = '';
        }
    }

    applySuggestion() {
        this.searchTerm = this.matchedSuggestion;
        this.matchedSuggestion = '';
    }
}

Pattern 2: Auto-Populating Related Record Fields via LDS

When creating or editing a transaction, entering a record ID or selecting a lookup record should instantly populate associated contact information (like Phone and Email) without requiring extra Apex queries.

HTML Template (recordAutofillForm.html):

<template>
    <lightning-card title="Record Lookup & Auto-Populate" icon-name="standard:contact">
        <div class="slds-p-around_medium">
            
            <!-- Input Target Record ID -->
            <div class="slds-m-bottom_medium">
                <lightning-input
                    label="Contact Record ID"
                    placeholder="Enter an 18-character Contact ID (e.g. 003...)"
                    value={contactId}
                    onchange={handleContactIdChange}>
                </lightning-input>
            </div>

            <!-- Auto-Populated Dependent Fields -->
            <div class="slds-grid slds-gutters slds-wrap">
                <div class="slds-col slds-size_1-of-1 slds-medium-size_1-of-2 slds-m-bottom_small">
                    <lightning-input 
                        label="Full Name" 
                        value={contactData.name} 
                        disabled>
                    </lightning-input>
                </div>
                <div class="slds-col slds-size_1-of-1 slds-medium-size_1-of-2 slds-m-bottom_small">
                    <lightning-input 
                        type="email" 
                        label="Email Address" 
                        value={contactData.email} 
                        disabled>
                    </lightning-input>
                </div>
                <div class="slds-col slds-size_1-of-1 slds-medium-size_1-of-2">
                    <lightning-input 
                        type="tel" 
                        label="Phone Number" 
                        value={contactData.phone} 
                        disabled>
                    </lightning-input>
                </div>
                <div class="slds-col slds-size_1-of-1 slds-medium-size_1-of-2">
                    <lightning-input 
                        label="Title / Role" 
                        value={contactData.title} 
                        disabled>
                    </lightning-input>
                </div>
            </div>

        </div>
    </lightning-card>
</template>

JavaScript Controller (recordAutofillForm.js):

import { LightningElement, wire } from 'lwc';
import { getRecord, getFieldValue } from 'lightning/uiRecordApi';

import NAME_FIELD from '@salesforce/schema/Contact.Name';
import EMAIL_FIELD from '@salesforce/schema/Contact.Email';
import PHONE_FIELD from '@salesforce/schema/Contact.Phone';
import TITLE_FIELD from '@salesforce/schema/Contact.Title';

const FIELDS = [NAME_FIELD, EMAIL_FIELD, PHONE_FIELD, TITLE_FIELD];

export default class RecordAutofillForm extends LightningElement {
    contactId = '';
    contactData = {
        name: '',
        email: '',
        phone: '',
        title: ''
    };

    handleContactIdChange(event) {
        const inputId = event.target.value.trim();
        // Trigger wire adapter when valid ID length is reached
        this.contactId = (inputId.length === 15 || inputId.length === 18) ? inputId : '';
    }

    @wire(getRecord, { recordId: '$contactId', fields: FIELDS })
    wiredContact({ data, error }) {
        if (data) {
            this.contactData = {
                name: getFieldValue(data, NAME_FIELD) || '',
                email: getFieldValue(data, EMAIL_FIELD) || '',
                phone: getFieldValue(data, PHONE_FIELD) || '',
                title: getFieldValue(data, TITLE_FIELD) || ''
            };
        } else if (error) {
            this.resetForm();
            console.error('Error fetching contact record:', error);
        } else {
            this.resetForm();
        }
    }

    resetForm() {
        this.contactData = { name: '', email: '', phone: '', title: '' };
    }
}
Warning Trap: Never use <lightning-input-field> outside of a parent <lightning-record-edit-form>. Standalone input fields must always use standard <lightning-input> controls bound to reactive JavaScript properties. Additionally, always use getFieldValue() rather than deep property drilling (data.fields.Name.value) to avoid null pointer exceptions on empty fields.
360 Architecture Summary:
  • Client Caching: getRecord caches retrieved records via Lightning Data Service (LDS), avoiding unnecessary server trips for previously fetched records.
  • Schema Referential Integrity: Always import field references (@salesforce/schema/Contact.Email) instead of using plain strings to prevent runtime errors if fields are renamed.
  • Debouncing High-Volume Inputs: For large suggestion lists or remote SOSL queries, wrap your onchange handler with a 300ms JavaScript debounce timer (setTimeout) to limit execution frequency.

Step 3: Configure Metadata and Deploy

Update recordAutofillForm.js-meta.xml to make the component available on Lightning record and app pages:

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>60.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>
Deployment & Testing:
# Deploy the component bundle
sf project deploy start

# Open target org in browser
sf org open
  • In Salesforce Setup, navigate to Lightning App Builder.
  • Place the autofill component onto an Account or Contact Record Page, then save and activate.
  • Enter an existing Contact record ID to confirm that all dependent contact fields populate instantly.
Core Takeaway: Using reactive wire adapters (getRecord) combined with getFieldValue delivers instantaneous, cached autofill capabilities that keep forms accurate and responsive.