AutoComplete

AutoComplete is an input component that provides real-time suggestions when being typed.

Usage#

import { AutoComplete } from 'primereact/autocomplete';
<AutoComplete.Root>
    <AutoComplete.Input />
    <AutoComplete.ClearIcon />
    <AutoComplete.Portal>
        <AutoComplete.Positioner>
            <AutoComplete.Panel>
                <AutoComplete.Header />
                <AutoComplete.List>
                    <AutoComplete.Options />
                </AutoComplete.List>
                <AutoComplete.Footer />
                <AutoComplete.Empty />
            </AutoComplete.Panel>
        </AutoComplete.Positioner>
    </AutoComplete.Portal>
</AutoComplete.Root>

Examples#

Basic#

AutoComplete is used as a controlled component with value and onValueChange properties along with an options collection. Label and value of an option are defined with the optionLabel and optionValue properties respectively. Note that, when options are simple primitive values such as a string array, no optionLabel and optionValue would be necessary.

basic-demo
'use client';
import type { AutoCompleteCompleteEvent } from '@primereact/types/shared/autocomplete';
import { AutoComplete } from '@primereact/ui/autocomplete';
import * as React from 'react';

interface Command {
    label: string;
    shortcut: string;
}

const commands: Command[] = [
    { label: 'New File', shortcut: '⌘N' },
    { label: 'Open File', shortcut: '⌘O' },
    { label: 'Save', shortcut: '⌘S' },
    { label: 'Save As', shortcut: '⇧⌘S' },
    { label: 'Find', shortcut: '⌘F' },
    { label: 'Replace', shortcut: '⌘H' },
    { label: 'Go to Line', shortcut: '⌘G' },
    { label: 'Toggle Sidebar', shortcut: '⌘B' },
    { label: 'Split Editor', shortcut: '⌘\\' },
    { label: 'Close Tab', shortcut: '⌘W' }
];

export default function BasicDemo() {
    const [filteredCommands, setFilteredCommands] = React.useState<Command[]>([]);

    const search = (event: AutoCompleteCompleteEvent) => {
        const query = event.query.toLowerCase();

        setFilteredCommands(query ? commands.filter((cmd) => cmd.label.toLowerCase().includes(query)) : [...commands]);
    };

    return (
        <div className="flex justify-center">
            <AutoComplete.Root options={filteredCommands} optionLabel="label" onComplete={search} className="w-full md:w-56">
                <AutoComplete.Value placeholder="Type a command..." className="w-full" />

                <AutoComplete.Portal>
                    <AutoComplete.Positioner>
                        <AutoComplete.Panel>
                            <AutoComplete.List>
                                <AutoComplete.Options style={{ maxHeight: '14rem' }}>
                                    {filteredCommands.map((cmd, index) => (
                                        <AutoComplete.Option key={cmd.label} index={index} uKey={cmd.label}>
                                            <div className="flex items-center justify-between w-full">
                                                <span>{cmd.label}</span>
                                                <kbd className="inline-flex items-center justify-center min-w-8 px-1.5 py-0.5 text-xs font-medium rounded bg-surface-100 dark:bg-surface-700 text-surface-600 dark:text-surface-300 border border-surface-200 dark:border-surface-600">
                                                    {cmd.shortcut}
                                                </kbd>
                                            </div>
                                        </AutoComplete.Option>
                                    ))}
                                </AutoComplete.Options>
                                <AutoComplete.Empty className="text-sm">No commands found</AutoComplete.Empty>
                            </AutoComplete.List>
                        </AutoComplete.Panel>
                    </AutoComplete.Positioner>
                </AutoComplete.Portal>
            </AutoComplete.Root>
        </div>
    );
}

Option#

Options can be defined manually using AutoComplete.Option component for custom rendering. Each option requires a uKey or index prop for identification. The optionKey property on the AutoComplete specifies which field from the data corresponds to the option keys.

option-demo
'use client';
import type { AutoCompleteCompleteEvent } from '@primereact/types/shared/autocomplete';
import { AutoComplete } from '@primereact/ui/autocomplete';
import { Avatar } from '@primereact/ui/avatar';
import * as React from 'react';

interface TeamMember {
    id: number;
    name: string;
    role: string;
    avatar: string;
    status: 'online' | 'away' | 'offline';
    statusClass: string;
}

const teamMembers: TeamMember[] = [
    { id: 1, name: 'Sarah Chen', role: 'Engineering Lead', avatar: 'SC', status: 'online', statusClass: 'bg-green-400' },
    { id: 2, name: 'Alex Rivera', role: 'Senior Developer', avatar: 'AR', status: 'online', statusClass: 'bg-green-400' },
    { id: 3, name: 'Jordan Kim', role: 'UX Designer', avatar: 'JK', status: 'away', statusClass: 'bg-amber-400' },
    { id: 4, name: 'Taylor Morgan', role: 'Product Manager', avatar: 'TM', status: 'offline', statusClass: 'bg-zinc-400' },
    { id: 5, name: 'Morgan Lee', role: 'DevOps Engineer', avatar: 'ML', status: 'online', statusClass: 'bg-green-400' },
    { id: 6, name: 'Casey Jones', role: 'QA Engineer', avatar: 'CJ', status: 'away', statusClass: 'bg-amber-400' }
];

export default function OptionDemo() {
    const [filteredMembers, setFilteredMembers] = React.useState<TeamMember[]>([]);

    const search = (event: AutoCompleteCompleteEvent) => {
        const query = event.query.toLowerCase();

        setFilteredMembers(
            query ? teamMembers.filter((m) => m.name.toLowerCase().includes(query) || m.role.toLowerCase().includes(query)) : [...teamMembers]
        );
    };

    return (
        <div className="flex justify-center">
            <AutoComplete.Root options={filteredMembers} optionLabel="name" onComplete={search} className="w-full md:w-56">
                <AutoComplete.Value placeholder="Search team members..." className="w-full" />

                <AutoComplete.Portal>
                    <AutoComplete.Positioner>
                        <AutoComplete.Panel>
                            <AutoComplete.List>
                                <AutoComplete.Options style={{ maxHeight: '16rem' }}>
                                    {filteredMembers.map((member, index) => (
                                        <AutoComplete.Option key={member.id} index={index} uKey={String(member.id)}>
                                            <div className="flex items-center gap-3 py-1">
                                                <div className="relative">
                                                    <Avatar.Root shape="circle" className="w-8 h-8">
                                                        <Avatar.Fallback>{member.avatar}</Avatar.Fallback>
                                                    </Avatar.Root>
                                                    <span
                                                        className={`absolute -bottom-0.5 -right-0.5 w-3 h-3 rounded-full border-2 border-surface-0 dark:border-surface-900 ${member.statusClass}`}
                                                    />
                                                </div>
                                                <div className="flex flex-col">
                                                    <span className="font-medium text-surface-900 dark:text-surface-0">{member.name}</span>
                                                    <span className="text-xs text-surface-500 dark:text-surface-400">{member.role}</span>
                                                </div>
                                            </div>
                                        </AutoComplete.Option>
                                    ))}
                                </AutoComplete.Options>
                                <AutoComplete.Empty className="text-sm">No members found</AutoComplete.Empty>
                            </AutoComplete.List>
                        </AutoComplete.Panel>
                    </AutoComplete.Positioner>
                </AutoComplete.Portal>
            </AutoComplete.Root>
        </div>
    );
}
dropdown-demo
'use client';
import type { AutoCompleteCompleteEvent } from '@primereact/types/shared/autocomplete';
import { AutoComplete } from '@primereact/ui/autocomplete';
import * as React from 'react';
import { ChevronDown } from '@primeicons/react/chevron-down';

export default function DropdownDemo() {
    const [items, setItems] = React.useState<string[] | number[]>([...Array(10).keys()]);

    const search = (event: AutoCompleteCompleteEvent) => {
        setItems(event.query ? [...Array(10).keys()].map((item) => event.query + '-' + item) : [...Array(10).keys()]);
    };

    return (
        <div className="flex justify-center">
            <AutoComplete.Root options={items} onComplete={search}>
                <AutoComplete.Value />

                <AutoComplete.Trigger>
                    <ChevronDown />
                </AutoComplete.Trigger>

                <AutoComplete.Portal>
                    <AutoComplete.Positioner>
                        <AutoComplete.Panel>
                            <AutoComplete.List>
                                <AutoComplete.Options style={{ maxHeight: '14rem' }} />
                            </AutoComplete.List>
                        </AutoComplete.Panel>
                    </AutoComplete.Positioner>
                </AutoComplete.Portal>
            </AutoComplete.Root>
        </div>
    );
}

Group#

Options can be organized into groups with headers. Use optionGroupLabel to specify the label field for groups and optionGroupChildren to define the field that contains the items in each group.

group-demo
'use client';
import type { AutoCompleteCompleteEvent } from '@primereact/types/shared/autocomplete';
import { AutoComplete } from '@primereact/ui/autocomplete';
import * as React from 'react';

interface Technology {
    label: string;
    value: string;
}

interface TechCategory {
    label: string;
    code: string;
    items: Technology[];
}

const techStack: TechCategory[] = [
    {
        label: 'Frontend',
        code: 'FE',
        items: [
            { label: 'React', value: 'react' },
            { label: 'Vue', value: 'vue' },
            { label: 'Angular', value: 'angular' },
            { label: 'Svelte', value: 'svelte' }
        ]
    },
    {
        label: 'Backend',
        code: 'BE',
        items: [
            { label: 'Node.js', value: 'nodejs' },
            { label: 'Python', value: 'python' },
            { label: 'Java', value: 'java' },
            { label: 'Go', value: 'go' }
        ]
    },
    {
        label: 'Database',
        code: 'DB',
        items: [
            { label: 'PostgreSQL', value: 'postgresql' },
            { label: 'MongoDB', value: 'mongodb' },
            { label: 'Redis', value: 'redis' },
            { label: 'MySQL', value: 'mysql' }
        ]
    }
];

const filterItems = (items: Technology[], query: string): Technology[] => {
    if (!query) return items;

    const normalizedQuery = query.toLowerCase();

    return items.filter((item) => item.label.toLowerCase().includes(normalizedQuery));
};

export default function GroupDemo() {
    const [filteredTech, setFilteredTech] = React.useState<TechCategory[]>([]);

    const search = (event: AutoCompleteCompleteEvent) => {
        const query = event.query;
        const _filteredTech: TechCategory[] = [];

        for (const category of techStack) {
            const filteredItems = filterItems(category.items, query);

            if (filteredItems.length) {
                _filteredTech.push({ ...category, items: filteredItems });
            }
        }

        setFilteredTech(_filteredTech);
    };

    return (
        <div className="flex justify-center">
            <AutoComplete.Root
                options={filteredTech}
                optionLabel="label"
                optionGroupLabel="label"
                optionGroupChildren="items"
                onComplete={search}
                className="w-full md:w-56"
            >
                <AutoComplete.Value placeholder="Search technologies..." className="w-full" />

                <AutoComplete.Portal>
                    <AutoComplete.Positioner>
                        <AutoComplete.Panel>
                            <AutoComplete.List>
                                <AutoComplete.Options style={{ maxHeight: '14rem' }} />
                                <AutoComplete.Empty className="text-sm">No option found</AutoComplete.Empty>
                            </AutoComplete.List>
                        </AutoComplete.Panel>
                    </AutoComplete.Positioner>
                </AutoComplete.Portal>
            </AutoComplete.Root>
        </div>
    );
}

Force Selection#

ForceSelection mode validates the manual input to check whether it also exists in the suggestions list, if not the input value is cleared to make sure the value passed to the model is always one of the suggestions. Simply enable forceSelection to enforce that input is always from the suggestion list.

forceselection-demo
'use client';
import { CountryService } from '@/shared/services/country.service';
import type { AutoCompleteCompleteEvent } from '@primereact/types/shared/autocomplete';
import { AutoComplete } from '@primereact/ui/autocomplete';
import * as React from 'react';

interface Country {
    name: string;
    code: string;
}

export default function ForceSelectionDemo() {
    const [countries, setCountries] = React.useState<Country[]>([]);
    const [filteredCountries, setFilteredCountries] = React.useState<Country[]>([]);

    React.useEffect(() => {
        CountryService.getCountries().then((data) => setCountries(data));
    }, []);

    const search = (event: AutoCompleteCompleteEvent) => {
        if (!event.query.trim().length) {
            setFilteredCountries(countries);
        } else {
            setFilteredCountries(
                countries.filter((country) => {
                    return country.name.toLowerCase().startsWith(event.query.toLowerCase());
                })
            );
        }
    };

    return (
        <div className="flex justify-center">
            <AutoComplete.Root
                options={filteredCountries}
                optionKey="code"
                optionLabel="name"
                forceSelection
                onComplete={search}
                className="w-full md:w-56"
            >
                <AutoComplete.Value className="w-full" />

                <AutoComplete.Portal>
                    <AutoComplete.Positioner>
                        <AutoComplete.Panel>
                            <AutoComplete.List>
                                <AutoComplete.Options style={{ maxHeight: '14rem' }} />
                                <AutoComplete.Empty className="text-sm">No countries found</AutoComplete.Empty>
                            </AutoComplete.List>
                        </AutoComplete.Panel>
                    </AutoComplete.Positioner>
                </AutoComplete.Portal>
            </AutoComplete.Root>
        </div>
    );
}

Float Label#

FloatLabel visually integrates a label with its form element. Visit FloatLabel documentation for more information.

float-label-demo
'use client';
import type { AutoCompleteCompleteEvent } from '@primereact/types/shared/autocomplete';
import { AutoComplete } from '@primereact/ui/autocomplete';
import { FloatLabel } from '@primereact/ui/floatlabel';
import { Label } from '@primereact/ui/label';
import * as React from 'react';

export default function FloatLabelDemo() {
    const [items, setItems] = React.useState<string[]>([]);

    const search = (event: AutoCompleteCompleteEvent) => {
        setItems([...Array(10).keys()].map((item) => event.query + '-' + item));
    };

    return (
        <div className="flex flex-wrap justify-center items-end gap-4">
            <FloatLabel>
                <AutoComplete.Root options={items} onComplete={search}>
                    <AutoComplete.Value id="over_label" />

                    <AutoComplete.Portal>
                        <AutoComplete.Positioner>
                            <AutoComplete.Panel>
                                <AutoComplete.List>
                                    <AutoComplete.Options style={{ maxHeight: '14rem' }} />
                                </AutoComplete.List>
                            </AutoComplete.Panel>
                        </AutoComplete.Positioner>
                    </AutoComplete.Portal>
                </AutoComplete.Root>

                <Label htmlFor="over_label">Over Label</Label>
            </FloatLabel>

            <FloatLabel variant="in">
                <AutoComplete.Root options={items} onComplete={search}>
                    <AutoComplete.Value id="in_label" />

                    <AutoComplete.Portal>
                        <AutoComplete.Positioner>
                            <AutoComplete.Panel>
                                <AutoComplete.List>
                                    <AutoComplete.Options style={{ maxHeight: '14rem' }} />
                                </AutoComplete.List>
                            </AutoComplete.Panel>
                        </AutoComplete.Positioner>
                    </AutoComplete.Portal>
                </AutoComplete.Root>

                <Label htmlFor="in_label">In Label</Label>
            </FloatLabel>

            <FloatLabel variant="on">
                <AutoComplete.Root options={items} onComplete={search}>
                    <AutoComplete.Value id="on_label" />

                    <AutoComplete.Portal>
                        <AutoComplete.Positioner>
                            <AutoComplete.Panel>
                                <AutoComplete.List>
                                    <AutoComplete.Options style={{ maxHeight: '14rem' }} />
                                </AutoComplete.List>
                            </AutoComplete.Panel>
                        </AutoComplete.Positioner>
                    </AutoComplete.Portal>
                </AutoComplete.Root>

                <Label htmlFor="on_label">On Label</Label>
            </FloatLabel>
        </div>
    );
}

Ifta Label#

IftaLabel is used to create infield top aligned labels. Visit IftaLabel documentation for more information.

ifta-label-demo
'use client';
import type { AutoCompleteCompleteEvent } from '@primereact/types/shared/autocomplete';
import { AutoComplete } from '@primereact/ui/autocomplete';
import { IftaLabel } from '@primereact/ui/iftalabel';
import { Label } from '@primereact/ui/label';
import * as React from 'react';

export default function IftaLabelDemo() {
    const [items, setItems] = React.useState<string[]>([]);

    const search = (event: AutoCompleteCompleteEvent) => {
        setItems([...Array(10).keys()].map((item) => event.query + '-' + item));
    };

    return (
        <div className="flex justify-center">
            <IftaLabel>
                <AutoComplete.Root options={items} variant="filled" onComplete={search} className="w-full md:w-56">
                    <AutoComplete.Value id="autocomplete" className="w-full" />

                    <AutoComplete.Portal>
                        <AutoComplete.Positioner>
                            <AutoComplete.Panel>
                                <AutoComplete.List>
                                    <AutoComplete.Options style={{ maxHeight: '14rem' }} />
                                </AutoComplete.List>
                            </AutoComplete.Panel>
                        </AutoComplete.Positioner>
                    </AutoComplete.Portal>
                </AutoComplete.Root>

                <Label htmlFor="autocomplete" className="mb-2">
                    Search
                </Label>
            </IftaLabel>
        </div>
    );
}

Clear Icon#

When AutoComplete.ClearIcon component is used, a clear icon is added to reset the AutoComplete.

clear-icon-demo
'use client';
import { Times } from '@primeicons/react/times';
import type { AutoCompleteCompleteEvent } from '@primereact/types/shared/autocomplete';
import { AutoComplete } from '@primereact/ui/autocomplete';
import { Tag } from '@primereact/ui/tag';
import * as React from 'react';

const productCategories = [
    { label: 'Electronics', value: 'electronics', count: 1247 },
    { label: 'Clothing', value: 'clothing', count: 856 },
    { label: 'Garden', value: 'home', count: 634 },
    { label: 'Sports', value: 'sports', count: 421 },
    { label: 'Books', value: 'books', count: 2103 },
    { label: 'Toys', value: 'toys', count: 312 }
];

export default function ClearIconDemo() {
    const [filteredCategories, setFilteredCategories] = React.useState<typeof productCategories>([]);

    const search = (event: AutoCompleteCompleteEvent) => {
        const query = event.query.toLowerCase();

        setFilteredCategories(query ? productCategories.filter((cat) => cat.label.toLowerCase().includes(query)) : [...productCategories]);
    };

    return (
        <div className="flex justify-center">
            <AutoComplete.Root options={filteredCategories} optionLabel="label" onComplete={search} className="w-full md:w-56">
                <AutoComplete.Value placeholder="Search categories..." className="w-full" />

                <AutoComplete.ClearIcon>
                    <Times />
                </AutoComplete.ClearIcon>

                <AutoComplete.Portal>
                    <AutoComplete.Positioner>
                        <AutoComplete.Panel>
                            <AutoComplete.List>
                                <AutoComplete.Options style={{ maxHeight: '14rem' }}>
                                    {filteredCategories.map((cat, index) => (
                                        <AutoComplete.Option key={cat.value} index={index} uKey={cat.value}>
                                            <div className="flex items-center justify-between w-full">
                                                <span>{cat.label}</span>
                                                <Tag severity="secondary" rounded>
                                                    {cat.count}
                                                </Tag>
                                            </div>
                                        </AutoComplete.Option>
                                    ))}
                                </AutoComplete.Options>
                                <AutoComplete.Empty className="text-sm">No categories found</AutoComplete.Empty>
                            </AutoComplete.List>
                        </AutoComplete.Panel>
                    </AutoComplete.Positioner>
                </AutoComplete.Portal>
            </AutoComplete.Root>
        </div>
    );
}

Checkmark#

A checkmark icon is displayed next to the selected option when checkmark property is enabled.

checkmark-demo
'use client';
import type { AutoCompleteCompleteEvent } from '@primereact/types/shared/autocomplete';
import { AutoComplete } from '@primereact/ui/autocomplete';
import * as React from 'react';

const languages = [
    { label: 'العربية', value: 'ar' },
    { label: 'Čeština', value: 'cs' },
    { label: 'Deutsch', value: 'de' },
    { label: 'Ελληνικά', value: 'el' },
    { label: 'English', value: 'en' },
    { label: 'Español', value: 'es' },
    { label: 'Français', value: 'fr' },
    { label: 'हिन्दी', value: 'hi' },
    { label: 'Bahasa Indonesia', value: 'id' },
    { label: 'Italiano', value: 'it' },
    { label: '日本語', value: 'ja' },
    { label: '한국어', value: 'ko' },
    { label: 'Nederlands', value: 'nl' },
    { label: 'Polski', value: 'pl' },
    { label: 'Português', value: 'pt' },
    { label: 'Română', value: 'ro' },
    { label: 'Русский', value: 'ru' },
    { label: 'Svenska', value: 'sv' },
    { label: 'Türkçe', value: 'tr' },
    { label: '中文', value: 'zh' }
];

export default function CheckmarkDemo() {
    const [filteredLanguages, setFilteredLanguages] = React.useState<(typeof languages)[number][]>([]);

    const search = (event: AutoCompleteCompleteEvent) => {
        const query = event.query.toLowerCase();

        setFilteredLanguages(query ? languages.filter((a) => a.label.toLowerCase().includes(query)) : [...languages]);
    };

    return (
        <div className="flex justify-center">
            <AutoComplete.Root
                checkmark
                options={filteredLanguages}
                optionKey="value"
                optionLabel="label"
                className="w-full md:w-64"
                onComplete={search}
            >
                <AutoComplete.Value placeholder="Search language..." className="w-full" />

                <AutoComplete.Portal>
                    <AutoComplete.Positioner>
                        <AutoComplete.Panel>
                            <AutoComplete.List>
                                <AutoComplete.Options />
                                <AutoComplete.Empty className="text-sm">No language found</AutoComplete.Empty>
                            </AutoComplete.List>
                        </AutoComplete.Panel>
                    </AutoComplete.Positioner>
                </AutoComplete.Portal>
            </AutoComplete.Root>
        </div>
    );
}

Loading#

loading-demo
'use client';
import { Spinner } from '@primeicons/react/spinner';
import type { AutoCompleteCompleteEvent } from '@primereact/types/shared/autocomplete';
import { AutoComplete } from '@primereact/ui/autocomplete';
import { InputGroup } from '@primereact/ui/inputgroup';
import * as React from 'react';

export default function BasicDemo() {
    const [items, setItems] = React.useState<string[]>([]);

    const search = (event: AutoCompleteCompleteEvent) => {
        setItems([...Array(10).keys()].map((item) => event.query + '-' + item));
    };

    return (
        <div className="flex justify-center">
            <AutoComplete.Root options={items} onComplete={search} className="w-full md:w-56">
                <InputGroup.Root>
                    <AutoComplete.Value className="w-full" />
                    <InputGroup.Addon>
                        <Spinner className="animate-spin" />
                    </InputGroup.Addon>
                </InputGroup.Root>

                <AutoComplete.Portal>
                    <AutoComplete.Positioner>
                        <AutoComplete.Panel>
                            <AutoComplete.List>
                                <AutoComplete.Options style={{ maxHeight: '14rem' }} />
                            </AutoComplete.List>
                        </AutoComplete.Panel>
                    </AutoComplete.Positioner>
                </AutoComplete.Portal>
            </AutoComplete.Root>
        </div>
    );
}

Sizes#

AutoComplete provides small and large sizes as alternatives to the base.

sizes-demo
'use client';
import type { AutoCompleteCompleteEvent } from '@primereact/types/shared/autocomplete';
import { AutoComplete } from '@primereact/ui/autocomplete';
import * as React from 'react';

export default function SizesDemo() {
    const [items, setItems] = React.useState<string[]>([]);

    const search = (event: AutoCompleteCompleteEvent) => {
        setItems([...Array(10).keys()].map((item) => event.query + '-' + item));
    };

    return (
        <div className="flex flex-col items-center gap-4">
            <AutoComplete.Root options={items} size="small" placeholder="Small" onComplete={search}>
                <AutoComplete.Value placeholder="Small" />

                <AutoComplete.Portal>
                    <AutoComplete.Positioner>
                        <AutoComplete.Panel>
                            <AutoComplete.List>
                                <AutoComplete.Options style={{ maxHeight: '14rem' }} />
                            </AutoComplete.List>
                        </AutoComplete.Panel>
                    </AutoComplete.Positioner>
                </AutoComplete.Portal>
            </AutoComplete.Root>

            <AutoComplete.Root options={items} placeholder="Normal" onComplete={search}>
                <AutoComplete.Value placeholder="Normal" />

                <AutoComplete.Portal>
                    <AutoComplete.Positioner>
                        <AutoComplete.Panel>
                            <AutoComplete.List>
                                <AutoComplete.Options style={{ maxHeight: '14rem' }} />
                            </AutoComplete.List>
                        </AutoComplete.Panel>
                    </AutoComplete.Positioner>
                </AutoComplete.Portal>
            </AutoComplete.Root>

            <AutoComplete.Root options={items} size="large" placeholder="Large" onComplete={search}>
                <AutoComplete.Value placeholder="Large" />

                <AutoComplete.Portal>
                    <AutoComplete.Positioner>
                        <AutoComplete.Panel>
                            <AutoComplete.List>
                                <AutoComplete.Options style={{ maxHeight: '14rem' }} />
                            </AutoComplete.List>
                        </AutoComplete.Panel>
                    </AutoComplete.Positioner>
                </AutoComplete.Portal>
            </AutoComplete.Root>
        </div>
    );
}

Fluid#

The fluid prop makes the component take up the full width of its container when set to true.

fluid-demo
'use client';
import type { AutoCompleteCompleteEvent } from '@primereact/types/shared/autocomplete';
import { AutoComplete } from '@primereact/ui/autocomplete';
import * as React from 'react';

export default function FluidDemo() {
    const [items, setItems] = React.useState<string[]>([]);

    const search = (event: AutoCompleteCompleteEvent) => {
        setItems([...Array(10).keys()].map((item) => event.query + '-' + item));
    };

    return (
        <div>
            <AutoComplete.Root options={items} fluid onComplete={search}>
                <AutoComplete.Value />

                <AutoComplete.Portal>
                    <AutoComplete.Positioner>
                        <AutoComplete.Panel>
                            <AutoComplete.List>
                                <AutoComplete.Options style={{ maxHeight: '14rem' }} />
                            </AutoComplete.List>
                        </AutoComplete.Panel>
                    </AutoComplete.Positioner>
                </AutoComplete.Portal>
            </AutoComplete.Root>
        </div>
    );
}

Filled#

Specify the filled property to display the component with a higher visual emphasis than the default outlined style.

filled-demo
'use client';
import type { AutoCompleteCompleteEvent } from '@primereact/types/shared/autocomplete';
import { AutoComplete } from '@primereact/ui/autocomplete';
import * as React from 'react';

export default function FilledDemo() {
    const [items, setItems] = React.useState<string[]>([]);

    const search = (event: AutoCompleteCompleteEvent) => {
        setItems([...Array(10).keys()].map((item) => event.query + '-' + item));
    };

    return (
        <div className="flex justify-center">
            <AutoComplete.Root options={items} variant="filled" onComplete={search} className="w-full md:w-56">
                <AutoComplete.Value className="w-full" />

                <AutoComplete.Portal>
                    <AutoComplete.Positioner>
                        <AutoComplete.Panel>
                            <AutoComplete.List>
                                <AutoComplete.Options style={{ maxHeight: '14rem' }} />
                            </AutoComplete.List>
                        </AutoComplete.Panel>
                    </AutoComplete.Positioner>
                </AutoComplete.Portal>
            </AutoComplete.Root>
        </div>
    );
}

Disabled#

Use the disabled property to disable a autocomplete.

disabled-demo
import { AutoComplete } from '@primereact/ui/autocomplete';

export default function DisabledDemo() {
    return (
        <div className="flex justify-center">
            <AutoComplete.Root options={[]} disabled className="w-full md:w-56">
                <AutoComplete.Value className="w-full" />

                <AutoComplete.Portal>
                    <AutoComplete.Positioner>
                        <AutoComplete.Panel>
                            <AutoComplete.List>
                                <AutoComplete.Options style={{ maxHeight: '14rem' }} />
                            </AutoComplete.List>
                        </AutoComplete.Panel>
                    </AutoComplete.Positioner>
                </AutoComplete.Portal>
            </AutoComplete.Root>
        </div>
    );
}

Invalid#

Specify the invalid property to display the component with a red border.

invalid-demo
'use client';
import type { AutoCompleteCompleteEvent } from '@primereact/types/shared/autocomplete';
import { AutoComplete } from '@primereact/ui/autocomplete';
import * as React from 'react';

export default function InvalidDemo() {
    const [value, setValue] = React.useState<string>('');
    const [value2, setValue2] = React.useState<string>('');
    const [items, setItems] = React.useState<string[]>([]);

    const search = (event: AutoCompleteCompleteEvent) => {
        setItems([...Array(10).keys()].map((item) => event.query + '-' + item));
    };

    return (
        <div className="flex flex-wrap justify-center gap-4">
            <AutoComplete.Root options={items} invalid={!value} placeholder="Search" onComplete={search}>
                <AutoComplete.Value value={value} onChange={(e: React.ChangeEvent<HTMLInputElement>) => setValue(e.target.value)} />

                <AutoComplete.Portal>
                    <AutoComplete.Positioner>
                        <AutoComplete.Panel>
                            <AutoComplete.List>
                                <AutoComplete.Options style={{ maxHeight: '14rem' }} />
                            </AutoComplete.List>
                        </AutoComplete.Panel>
                    </AutoComplete.Positioner>
                </AutoComplete.Portal>
            </AutoComplete.Root>

            <AutoComplete.Root options={items} invalid={!value2} variant="filled" placeholder="Search" onComplete={search}>
                <AutoComplete.Value value={value2} onChange={(e: React.ChangeEvent<HTMLInputElement>) => setValue2(e.target.value)} />

                <AutoComplete.Portal>
                    <AutoComplete.Positioner>
                        <AutoComplete.Panel>
                            <AutoComplete.List>
                                <AutoComplete.Options style={{ maxHeight: '14rem' }} />
                            </AutoComplete.List>
                        </AutoComplete.Panel>
                    </AutoComplete.Positioner>
                </AutoComplete.Portal>
            </AutoComplete.Root>
        </div>
    );
}

Accessibility#

The input element has combobox role in addition to aria-autocomplete, aria-haspopup and aria-expanded attributes. The relation between the input and the popup is created with aria-controls and aria-activedescendant attribute is used to instruct screen reader which option to read during keyboard navigation within the popup list.

In multiple mode, chip list uses listbox role with aria-orientation set to horizontal whereas each chip has the option role with aria-label set to the label of the chip.

The popup list has an id that refers to the aria-controls attribute of the input element and uses listbox as the role. Each list item has option role and an id to match the aria-activedescendant of the input element.

Closed State Keyboard Support#

KeyFunction
tabMoves focus to the autocomplete element.
any printable characterOpens the popup and moves focus to the first option.
KeyFunction
tabMoves focus to the next focusable element in the popup. If there is none, the focusable option is selected and the overlay is closed then moves focus to next element in page.
shift + tabMoves focus to the previous focusable element in the popup. If there is none, the focusable option is selected and the overlay is closed then moves focus to next element in page.
enterSelects the focused option and closes the popup, then moves focus to the autocomplete element.
spaceSelects the focused option and closes the popup, then moves focus to the autocomplete element.
escapeCloses the popup, then moves focus to the autocomplete element.
down arrowMoves focus to the next option, if there is none then visual focus does not change.
up arrowMoves focus to the previous option, if there is none then visual focus does not change.
alt + up arrowSelects the focused option and closes the popup, then moves focus to the autocomplete element.
left arrowRemoves the visual focus from the current option and moves input cursor to one character left.
right arrowRemoves the visual focus from the current option and moves input cursor to one character right.
homeMoves input cursor at the end, if not then moves focus to the first option.
endMoves input cursor at the beginning, if not then moves focus to the last option.
pageUpJumps visual focus to first option.
pageDownJumps visual focus to last option.