Data Options

Single Select

const Example1 = () => {
    const options = [{text: 'Jane Doe',value: 1},{text: 'Bob Ross',value: 2},{text: 'Jackie Robinson',value: 3},{text: 'Alexandria Garcia',value: 4}];
    const [value, setValue] = React.useState({text: 'Bob Ross',value: 2});
    return (
        <div style={{height: '230px'}}>
            <Form.AnvilSelect
                value={value}
                onChange={setValue}
                options={options}
                label="Technician"
                trigger={{placeholder: 'Select a Technician'}}
                open={true}
                autoFlipVertically={false}
                closeOnClickOutside={false}
            />
        </div>
    );
}
render (Example1);

Multiselect

Selects can also allow for multiple selections. Each option in a multiselect has a built-in Checkbox as a visual aid.

const Example2 = () => {
    const options = [{text: 'Jane Doe',value: 1},{text: 'Bob Ross',value: 2},{text: 'Jackie Robinson',value: 3},{text: 'Alexandria Garcia',value: 4}];
    const [value, setValue] = React.useState([{text: 'Bob Ross',value: 2},{text: 'Jackie Robinson',value: 3}]);
    return (
        <div style={{height: '200px'}}>
            <AnvilSelect
                multiple
                value={value}
                onChange={setValue}
                options={options}
                trigger={{placeholder: 'Select Technicians'}}
                open={true}
                closeOnClickOutside={false}
                autoFlipVertically={false}
            />
        </div>
    );
}
render (Example2);

Grouped Options

Options in a Select can be grouped together.

const Example3 = () => {
    const options = [
        {
            text: 'Western Division',
            options: [
                {
                    content: 'Plumbing',
                    text: 'Plumbing Western Division',
                    value: '1',
                }, {
                    text: 'HVAC',
                    text: 'HVAC Western Division',
                    value: '2'
                }
            ]
        },
        {
            text: 'Eastern Division',
            options: [
                {
                    content: 'Plumbing',
                    text: 'Plumbing Eastern Division',
                    value: '3',
                }, {
                    text: 'HVAC Install',
                    text: 'HVAC Install Eastern Division',
                    value: '4'
                }, {
                    text: 'Electrician',
                    text: 'Electrician Eastern Division',
                    value: '5'
                }
            ]
        }
    ];
    return (
        <div style={{height: '320px'}}>
            <AnvilSelect
                options={options}
                trigger={{placeholder: 'Select a Unit'}}
                open={true}
                closeOnClickOutside={false}
        autoFlipVertically={false}
            />
        </div>
    );
}
render (Example3);

Customized Options

The choices in the Select can be customized to produce many unique stylings. This can be useful when additional information can enhance the functionality of the Select.

const Example4 = () => {
    const options = [{text: 'Jane Doe',value: 1},{text: 'Bob Ross',value: 2},{text: 'Jackie Robinson',value: 3},{text: 'Alexandria Garcia',value: 4},{text: 'Zack Bower',value: 5}];
    const customOptions = options.map((option) => {
        const object = {
            text: option.text,
            value: option.value,
            content: (
                <Stack alignItems="center" spacing={1}>
                    <Avatar size="s" autoColor name={option.text} />
                    <BodyText>{option.text}</BodyText>
                </Stack>
            )
        };
        return object;
    });

    return (
        <div style={{height: '300px'}}>
            <Form.AnvilSelect
                label="Select a Technician"
                options={customOptions}
                trigger={{placeholder: 'Technicians'}}
                open={true}
                closeOnClickOutside={false}
        autoFlipVertically={false}
            />
        </div>
    );
}
render (Example4);
<div style={{height: '200px'}}>
    <Form.AnvilSelect
        label="Unit Selection"
        options={[
            {
                key: 1,
                text: 'A/C Unit I ($2950)',
                value: 1,
                content: (
                    <Stack alignItems='center' justifyContent='space-between' className="w-100">
                        <BodyText size='small' className="lh-1">A/C Unit I</BodyText>
                        <Tag compact badge color="success" subtle>$2950</Tag>
                    </Stack>
                )
            },
            {
                key: 2,
                text: 'A/C Unit II ($3450)',
                value: 2,
                content: (
                    <Stack alignItems='center' justifyContent='space-between'>
                        <BodyText size='small' className="lh-1">A/C Unit II</BodyText>
                        <Tag compact badge color="success" subtle>$3450</Tag>
                    </Stack>
                )
            },
            {
                key: 3,
                text: 'A/C Unit III ($4830)',
                value: 3,
                content: (
                    <Stack alignItems='center' justifyContent='space-between'>
                        <Stack.Item><BodyText size='small' className="lh-1 d-ib m-r-half">A/C Unit III</BodyText> <Tag compact subtle>Best Value</Tag></Stack.Item>
                        <Tag compact badge color="success" subtle>$4830</Tag>
                    </Stack>
                )
            },
        ]}
        trigger={{placeholder: 'Technicians'}}
        open={true}
        closeOnClickOutside={false}
        autoFlipVertically={false}
    />
</div>
<div style={{height: '250px'}}>
    <Form.AnvilSelect
        multiple
        label="Email"
        options={[
            {
                key: 1,
                text: 'First Time',
                value: 1,
                content: (
                    <div className="m-l-half">
                        <BodyText size='small' className="lh-display m-b-half">First time users</BodyText>
                        <BodyText size='xsmall' subdued className="lh-display">Recently subscribed to system</BodyText>
                    </div>
                )
            },
            {
                key: 2,
                text: 'Low Response',
                value: 2,
                content: (
                    <div className="m-l-half">
                        <BodyText size='small' className="lh-display m-b-half">Low response</BodyText>
                        <BodyText size='xsmall' subdued className="lh-display">No response in the last 60 days</BodyText>
                    </div>
                )
            },
            {
                key: 3,
                text: 'Active Engagement',
                value: 3,
                content: (
                    <div className="m-l-half">
                        <BodyText size='small' className="lh-display m-b-half">Active engagement</BodyText>
                        <BodyText size='xsmall' subdued className="lh-display">Frequent responders to campaigns</BodyText>
                    </div>
                )
            },
        ]}
        trigger={{placeholder: 'Technicians'}}
        open={true}
        closeOnClickOutside={false}
        autoFlipVertically={false}
    />
</div>

Secondary Actions

A secondary action can be performed on individual options. Example actions include editing, deleting, or navigating to more information. Secondary actions are only visible on hover.

const Example5 = () => {
    const options = [{text: 'Jane Doe',value: 1, secondaryAction: (<Button xsmall primary fill="subtle" onClick={() => alert("Action Clicked")}>Action</Button>) },{text: 'Bob Ross',value: 2, secondaryAction: (<Tooltip text='Edit'><Button iconName="edit" xsmall primary fill="subtle" onClick={() => alert("Action Clicked")}/></Tooltip>)},{text: 'Jackie Robinson',value: 3, secondaryAction: (<Stack spacing={1}><Tooltip text='Edit'><Button iconName="edit" xsmall primary fill="subtle" onClick={() => alert("Action Clicked")}/></Tooltip><Tooltip direction='tl' text='Delete'><Button iconName="delete" xsmall primary fill="subtle" onClick={() => alert("Action Clicked")}/></Tooltip></Stack>)}];

    return (
        <div style={{height: '170px'}}>
            <AnvilSelect
                options={options}
                trigger={{placeholder: 'Hover over an option'}}
                open={true}
                closeOnClickOutside={false}
        autoFlipVertically={false}
            />
        </div>
    );
}
render (Example5);

Empty State

Displayed when there are no options available, typically discovered when searching a Select.

<div style={{height: '170px'}}>
    <AnvilSelect
        search
        options={[]}
        trigger={{placeholder: 'Select a Technician'}}
        open={true}
        closeOnClickOutside={false}
        autoFlipVertically={false}
    />
</div>

Trigger

Select Addons

Select Addons can be added to help describe the content. They can be used to help with formatting or show contextual indicators of the content we’re asking for.

<Form>
    <Form.AnvilSelect
        options={[]}
        label="Small Select"
        trigger={{
            shortLabel: '$'
        }}
    />
    <Form.AnvilSelect
        options={[]}
        label="Small Select"
        trigger={{
            shortLabel: '$',
            shortLabelPosition: 'right'
        }}
    />
    <Form.AnvilSelect
        options={[]}
        label="Large Select"
        trigger={{
            shortLabel: <Icon name="event" />
        }}
    />
</Form>

With Description

const Example9 = () => {
    const options = [];
    const [value, setValue] = React.useState([]);
    return (
        <Form.AnvilSelect
            value={value}
            onChange={setValue}
            options={options}
            label="Technician"
            trigger={{placeholder: 'Select a Technician', shortLabel: <Icon name="person" />}}
            description="Description goes here..."
        />
    );
}
render (Example9);

Error State

const Example9 = () => {
    const options = [{text: 'Jane Doe',value: 1},{text: 'Bob Ross',value: 2},{text: 'Jackie Robinson',value: 3},{text: 'Alexandria Garcia',value: 4}];
    const [value, setValue] = React.useState({text: 'Bob Ross',value: 2});
    return (
        <div style={{height: '230px'}}>
            <Form.AnvilSelect
                value={value}
                onChange={setValue}
                options={options}
                label="Technician"
                trigger={{error: true, placeholder: 'Select a Technician', shortLabel: <Icon name="person" />}}
                open={true}
                closeOnClickOutside={false}
                autoFlipVertically={false}
            />
        </div>
    );
}
render (Example9);
const Example9 = () => {
    const options = [];
    const [value, setValue] = React.useState([]);
    return (
        <Form.AnvilSelect
            value={value}
            onChange={setValue}
            options={options}
            label="Technician"
            trigger={{error: true, placeholder: 'Select a Technician', shortLabel: <Icon name="person" />}}
            error="You must choose a technician."
        />
    );
}
render (Example9);

Trigger Sizes

The Select's trigger can be configured into three sizes

const Example10 = () => {
    const options = [];

    return (
        <Form>
            <Form.AnvilSelect
                options={options}
                label="Small Select"
                trigger={{size: 'small'}}
            />
            <Form.AnvilSelect
                options={options}
                label="Default Select"
                trigger={{}}
            />
            <Form.AnvilSelect
                options={options}
                label="Large Select"
                trigger={{size: 'large'}}
            />
        </Form>
    );
}
render (Example10);

Tags

Tag display on selection

In multiselects, tags are populated in the trigger for each selection. This allows for a quick readout of selections, but this can quickly get out of hand. By default, the Select will display an X Selected when the selections span across more than 1 row, which can be configured for specific needs.

const Example6 = () => {
    const options = [{text: 'Jane Doe',value: 1},{text: 'Bob Ross',value: 2},{text: 'Jackie Robinson',value: 3},{text: 'Alexandria Garcia',value: 4},{text: 'Zack Bower',value: 5},{text: 'Erin Smith',value: 6},{text: 'Jarrod Saltalamacchia',value: 7},{text: 'Natalia McPhearson',value: 8}];
    const [value, setValue] = React.useState(options);
    return (
        <AnvilSelect
            multiple
            value={value}
            onChange={setValue}
            options={options}
            trigger={{placeholder: 'Technicians', rows: 1}}
        />
    );
}
render (Example6);
const Example7 = () => {
    const options = [{text: 'Jane Doe',value: 1},{text: 'Bob Ross',value: 2},{text: 'Jackie Robinson',value: 3},{text: 'Alexandria Garcia',value: 4},{text: 'Zack Bower',value: 5},{text: 'Erin Smith',value: 6},{text: 'Jarrod Saltalamacchia',value: 7},{text: 'Natalia McPhearson',value: 8}];
    const [value, setValue] = React.useState(options);
    return (
        <AnvilSelect
            multiple
            value={value}
            onChange={setValue}
            options={options}
            trigger={{placeholder: 'Technicians', rows: 0}}
        />
    );
}
render (Example7);

Custom Tags

Multiselects can take advantage of tag's custom color options.

const Example8 = () => {
    const options = [{text: 'Red', value: 1, color: tokens.colorRed},{text: 'Blue', value: 2, color: 'rgb(0, 0, 255)'},{text: 'Green', value: 3, color: '#00FF00'}];
    const [value, setValue] = React.useState(options);
    return (
        <AnvilSelect
            value={value}
            onChange={setValue}
            multiple
            options={options}
            trigger={{placeholder: 'Colors'}}
        />
    );
}
render (Example8);

Label

Label Help

Labels can have a help icon with a tooltip to provide additional context to a label.

<Form>
    <Form.AnvilSelect
        options={[]}
        label="Select"
        labelProps={{
            help: "This is help text"
        }}
    />
</Form>

Required and Optional

A visual indicator can be applied on a Select's label.

<Form>
    <Form.AnvilSelect
        label="Required Label"
        options={[]}
        labelProps={{
            required: true
        }}
    />
    <Form.AnvilSelect
        label="Optional Label"
        options={[]}
        labelProps={{
            optional: true
        }}
    />
</Form>

Header

Options within a select can be filtered through a search functionality. Search is useful with 10+ options available. The more options there are, the more desirable search functionality becomes. Search is also useful when the user knows what they are looking for (such as a specific person).

const Example11 = () => {
    const options = [{text: 'Jane Doe',value: 1},{text: 'Bob Ross',value: 2},{text: 'Jackie Robinson',value: 3},{text: 'Alexandria Garcia',value: 4}];

    return (
        <div style={{height: '270px'}}>
            <AnvilSelect
                search={{
                    placeholder: "Search for a Technician"
                }}
                options={options}
                trigger={{placeholder: 'Select a Technician'}}
                open={true}
                closeOnClickOutside={false}
                autoFlipVertically={false}
            />
        </div>
    );
}
render (Example11);

Footer

Select All

In multiselects, all options can be selected at once. There is also an option to select all items from within a single group of content.

const Example12 = () => {
    const options = [{text: 'Jane Doe',value: 1},{text: 'Bob Ross',value: 2},{text: 'Jackie Robinson',value: 3}];

    return (
        <div style={{height: '220px'}}>
            <AnvilSelect
                multiple={{selectAll: true}}
                options={options}
                trigger={{placeholder: 'Select a Technician'}}
                open={true}
                closeOnClickOutside={false}
                autoFlipVertically={false}
            />
        </div>
    );
}
render (Example12);

Apply Selections

The Select allows for an option to delay applying selections until an explicit apply action is given by a user. This can be useful when selections update content on a page, where refreshing the page after each selection is unnecessary.

const Example13 = () => {
    const options = [{text: 'Jane Doe',value: 1},{text: 'Bob Ross',value: 2},{text: 'Jackie Robinson',value: 3}];

    return (
        <div style={{height: '220px'}}>
            <AnvilSelect
                multiple
                footer={{
                    actionName: 'Apply',
                    onActionClick: (() => alert("Apply button clicked"))
                }}
                options={options}
                trigger={{placeholder: 'Select a Technician'}}
                open={true}
                closeOnClickOutside={false}
                autoFlipVertically={false}
            />
        </div>
    );
}
render (Example13);

Body Options

Scrollable

Like the Popover, the Select's body content can be scrolled through. By default, it begins scrolling after it has reached 90% screen height, but can be customized to a specific pixel value.

const Example14 = () => {
    const options = [{text: 'Jane Doe',value: 1},{text: 'Bob Ross',value: 2},{text: 'Jackie Robinson',value: 3},{text: 'Alexandria Garcia',value: 4},{text: 'John Doe',value: 16},{text: 'Erica K',value: 5},{text: 'Moses Brooks',value: 6},{text: 'Pam Colin',value: 7},{text: 'Jackie Johnson',value: 8},{text: 'Jane Doe',value: 9},{text: 'Bob Ross',value: 10},{text: 'Jackie Robinson',value: 11},{text: 'Alexandria Garcia',value: 12},{text: 'Erica K',value: 13},{text: 'Moses Brooks',value: 14},{text: 'Pam Colin',value: 15}];
    const [value, setValue] = React.useState({text: 'Bob Ross',value: 2});
    return (
        <div style={{height: '330px'}}>
            <Form.AnvilSelect
                value={value}
                onChange={setValue}
                options={options}
                label="Technician"
                trigger={{placeholder: 'Select a Technician', shortLabel: <Icon name="person" />}}
                open={true}
                closeOnClickOutside={false}
                scrollHeight={'250px'}
                autoFlipVertically={false}
            />
        </div>
    );
}
render (Example14);

Popover Sizing

By default, the Select's trigger and its popover are the same width. The popover part of the Select can also be a custom width, which can be useful when there is little real estate for the trigger.

const Example15 = () => {
    const options = [{text: 'Jane Doe',value: 1},{text: 'Bob Ross',value: 2},{text: 'Jackie Robinson',value: 3},{text: 'Alexandria Garcia',value: 4},{text: 'Zack Bower',value: 5},{text: 'Erin Smith',value: 6},{text: 'Jarrod Saltalamacchia',value: 7},{text: 'Natalia McPhearson',value: 8}];

    return (
        <AnvilSelect
            multiple
            options={options}
            trigger={{placeholder: 'Technicians', rows: 0}}
            popoverWidth="m"
        />
    );
}
render (Example15);

Drill-in State

A select has a secondary, drilled-in state that can be accessed through a Select. Like the Popover component, this content can be customized into any format.

const Example16 = () => {
    const [open, setOpen] = React.useState(true);
    const toggleDrillIn = () => { setOpen(!open) };
    const options = [{text: 'Jane Doe',value: 1, secondaryAction: (<Button xsmall primary fill="subtle" onClick={toggleDrillIn}>Click me</Button> ) } ];

    return (
        <div style={{height: '210px'}}>
            <AnvilSelect
                search
                options={options}
                trigger={{placeholder: 'Select a Technician'}}
                open={true}
                closeOnClickOutside={false}
                autoFlipVertically={false}
                drillIn={{
                    open: open,
                    content: 'A blank canvas for any type of content',
                    title: 'This is a title',
                    footerActionName: 'Apply',
                    footerOnActionClick: toggleDrillIn,
                    onBack: toggleDrillIn
                }}
            />
        </div>
    );
}
render (Example16);
const Example17 = () => {
    const [open, setOpen] = React.useState(true);
    const [state, setState] = React.useState(1);
    const toggleDrillIn = () => { setOpen(!open) };
    const options = [{text: 'Jane Doe',value: 1, secondaryAction: (<Button xsmall primary fill="subtle" onClick={toggleDrillIn}>Click me</Button> ) } ];
    const secondOptions = [{text: 'California',value: 1},{text: 'Arizonda',value: 2},{text: 'New Mexico',value: 3},{text: 'Nevada',value: 4}, {text: 'Utah',value: 5}];

    return (
        <div style={{height: '360px'}}>
            <AnvilSelect
                search
                options={options}
                trigger={{placeholder: 'Select a Technician'}}
                open={true}
                closeOnClickOutside={false}
                autoFlipVertically={false}
                drillIn={{
                    open: open,
                    content: (
                        <Form>
                            <Form.AnvilSelect
                                label="State"
                                options={secondOptions}
                                trigger={{placeholder: 'Select a Technician'}}
                                open={state.secondSelectOpen}
                            />
                        <Form.ButtonToggle
                            value={state}
                            small
                            label="Sent by"
                            onChange={(value) => setState(value)}
                            options={[
                                {
                                    text: 'Email',
                                    value: 1
                                },
                                {
                                    text: 'Phone',
                                    value: 2
                                }
                            ]}
                        />
                        </Form>
                    ),
                    title: 'This is a title',
                    footerActionName: 'Apply',
                    footerOnActionClick: toggleDrillIn,
                    onBack: toggleDrillIn
                }}
            />
        </div>
    );
}
render (Example17);

Use Cases

Sorting Options

The Select does not give an opinion on how choices are sorted. Common types of sorting include alphabetical, time-based, and categorical. Groups can also help in sorting information. The sort type should match up to what a user expects

const Example18 = () => {
    const timeOptions = [{text: 'January', value: 1},{text: 'February', value: 2},{text: 'March', value: 3},{text: 'April', value: 4}];
    const hierarchyOptions = [{text: 'less than', value: 1},{text: 'greater than', value: 2},{text: 'equal to', value: 3}];
    const sizeOptions = [{text: 'Small', value: 1},{text: 'Medium', value: 2},{text: 'Large', value: 3},{text: 'Extra Large', value: 4}];
    const techOptions = [{text: 'Ariel Somebody', value: 1},{text: 'Bob Someone', value: 2},{text: 'Caroline Someperson', value: 3},{text: 'Derrek Something', value: 4}];

    return (
        <Form style={{height: '220px'}}>
            <Form.Group widths="equal">
                <Form.AnvilSelect
                    options={timeOptions}
                    trigger={{placeholder: 'Month'}}
                    open={true}
                    closeOnClickOutside={false}
                    autoFlipVertically={false}
                />
                <Form.AnvilSelect
                    options={hierarchyOptions}
                    trigger={{placeholder: 'is...'}}
                    open={true}
                    closeOnClickOutside={false}
                    autoFlipVertically={false}
                />
                <Form.AnvilSelect
                    options={sizeOptions}
                    trigger={{placeholder: 'Size',}}
                    open={true}
                    closeOnClickOutside={false}
                    autoFlipVertically={false}
                />
                <Form.AnvilSelect
                    options={techOptions}
                    trigger={{placeholder: 'Technician',}}
                    open={true}
                    closeOnClickOutside={false}
                    autoFlipVertically={false}
                />
            </Form.Group>
        </Form>
    );
}
render (Example18);

Async Select

For Selects that have to fetch options from a remote server, we use the AnvilSelect.useAsync hook and allow passing of a callback which takes over the default search functionality. It should return a promise of options.

const { useAsync } = AnvilSelect;
let timeoutId;
let rejectFoo;
function cancelFetchOptions(message) {
    clearTimeout(timeoutId);
    rejectFoo && rejectFoo(message);
}
async function fetchOptions(searchString) {
    const options = [
        {value: 1, text: 'Australia'},
        {value: 2, text: 'America'},
        {value: 3, text: 'New Zealand'},
        {value: 4, text: 'Spain'},
        {value: 5, text: 'Turkey'},
        {value: 6, text: 'India'},
        {value: 7, text: 'Russia'},
        {value: 8, text: 'Poland'},
        {value: 9, text: 'Canada'},
    ];
    // simulating remote api call
    var res = await  new Promise((resolve, reject) => {
        rejectFoo = reject;
        timeoutId = setTimeout(() => {
            const resultNumber = 3;
            const filteredOptions = options.filter(
                o => o.text.toLowerCase().includes(searchString.toLowerCase())
            );
            if (filteredOptions.length > resultNumber) {
                filteredOptions.length = resultNumber;
            }
            resolve(filteredOptions);
        }, 1000);
    });
    return res;
}

const InitialOptionsExample = () => {
    const [value, setValue] = React.useState();

    const asyncProps = useAsync({
        value,
        fetchOptions,
        cancelFetchOptions,
        search: {
            placeholder: "Type here or select from list"
        },
    });

    return (
        <Form>
            <Form.AnvilSelect
                label="Fetch on render"
                onChange={setValue}
                {...asyncProps}
            />
        </Form>
    );
};
render(InitialOptionsExample);
const { useAsync } = AnvilSelect;
let timeoutId;
let rejectFoo;
function cancelFetchOptions(message) {
    clearTimeout(timeoutId);
    rejectFoo && rejectFoo(message);
}
async function fetchOptions(searchString) {
    const options = [
        {value: 1, text: 'Australia'},
        {value: 2, text: 'America'},
        {value: 3, text: 'New Zealand'},
        {value: 4, text: 'Spain'},
        {value: 5, text: 'Turkey'},
        {value: 6, text: 'India'},
        {value: 7, text: 'Russia'},
        {value: 8, text: 'Poland'},
        {value: 9, text: 'Canada'},
    ];
    // simulating remote api call
    var res = await  new Promise((resolve, reject) => {
        rejectFoo = reject;
        timeoutId = setTimeout(() => {
            const resultNumber = 3;
            const filteredOptions = options.filter(
                o => o.text.toLowerCase().includes(searchString.toLowerCase())
            );
            if (filteredOptions.length > resultNumber) {
                filteredOptions.length = resultNumber;
            }
            resolve(filteredOptions);
        }, 1000);
    });
    return res;
}

const FetchOnFocusExample = () => {
    const [value, setValue] = React.useState();

    const asyncProps = useAsync({
        value,
        fetchOptions,
        cancelFetchOptions,
        fetchOnOpen: true,
    });

    return (
        <Form>
            <Form.AnvilSelect
                label="Fetch on open"
                onChange={setValue}
                {...asyncProps}
            />
        </Form>
    );
};
render(FetchOnFocusExample);
const { useAsync } = AnvilSelect;
let timeoutId;
let rejectFoo;
function cancelFetchOptions(message) {
    clearTimeout(timeoutId);
    rejectFoo && rejectFoo(message);
}
async function fetchOptions(searchString) {
    const options = [
        {value: 1, text: 'Australia'},
        {value: 2, text: 'America'},
        {value: 3, text: 'New Zealand'},
        {value: 4, text: 'Spain'},
        {value: 5, text: 'Turkey'},
        {value: 6, text: 'India'},
        {value: 7, text: 'Russia'},
        {value: 8, text: 'Poland'},
        {value: 9, text: 'Canada'},
    ];
    // simulating remote api call
    var res = await  new Promise((resolve, reject) => {
        rejectFoo = reject;
        timeoutId = setTimeout(() => {
            const resultNumber = 3;
            const filteredOptions = options.filter(
                o => o.text.toLowerCase().includes(searchString.toLowerCase())
            );
            if (filteredOptions.length > resultNumber) {
                filteredOptions.length = resultNumber;
            }
            resolve(filteredOptions);
        }, 1000);
    });
    return res;
}

const FetchOnFocusWithMultipleSelectExample = () => {
    const [value, setValue] = React.useState([
        {value: 1, text: 'Australia'},
        {value: 2, text: 'America'},
    ]);

    const asyncProps = useAsync({
        value,
        fetchOptions,
        cancelFetchOptions,
        fetchOnOpen: true,
        search: {
            placeholder: "Type here or select from list"
        },
    });

    return (
        <Form>
            <Form.AnvilSelect
                label="Fetch on open with multiple Select"
                onChange={setValue}
                closeOnClickOutside={false}
                multiple={true}
                {...asyncProps}
            />
        </Form>
    );
};
render(FetchOnFocusWithMultipleSelectExample);

When to use a Select

  • There are at least 5 choices.

  • There is a default, recommended option.

  • Space is at a premium in the interface.

  • When search functionality is useful to narrow options.

When not to use a Select

  • For navigation. Use an action menu for similar behavior to a Select.

  • For commands or actions. Use an action menu in its place.

Caution in using a Select

It is easy to overuse the Select, as it can be used to hide complexity on the page. Discoverability of choices can be obscured when hidden via a Select.

  • For less than 5 options, and screen space is not constrained. Checkboxes for multi-select or Radios for single select may be better.

  • For more than 30 options. Search is highly encouraged for many options. There is not a definitive component for hundreds of choices: a table (data list, Kendo), a Modal, a complex Popover, or a Drawer.

  • When a user benefits from scanning the options, visible Checkbox or Radios on the page allows for more emphasis.

Related Components

  • To build a full form, use the Form component.

  • For less than 5 options, a Radio or Checkbox list surfaces options faster.