Sorry, but you either have no stories or none are selected somehow.
If the problem persists, check the browser console, or the terminal you've run Storybook from.
The component failed to render properly, likely due to a configuration issue in Storybook. Here are some common causes and how you can address them:
Select is the base for every component on this page. The approaches mentioned here are also applicable to AsyncSelect
, MultiSelect
, AsyncMultiSelect
.
Select is an input with the ability to search and create new values. It should be used when you have a list of options. If the data has a tree structure, consider using Cascader
instead.
Select has some features:
There are four properties for each option:
label
- Text that is visible in the menu.value
- Could be anything, but is usually a string. Used to identify what is actually selected.description
- Longer description that describes the choice. Use this sparingly.imgUrl
- URL to an image. Use this when an image or icon provides more context for the option.const options = [ { label: 'Basic option', value: 0 }, { label: 'Option with description', value: 1, description: 'this is a description' }, { label: 'Option with description and image', value: 2, description: 'This is a very elaborate description, describing all the wonders in the world.', imgUrl: 'https://placekitten.com/40/40', }, ];
Creatable option is used when you want to be able to add a custom value to the list of options. allowCustomValue
needs to be true and you must handle the value creation with onCreateOption
.
import { Select } from "@grafana/ui"; const SelectComponent = () => { const [value, setValue] = useState<SelectableValue<number>>(); return ( <Select options={option} value={value} allowCustomValue onCreateOption={customValue => { setValue(customValue); }} /> ); };
If you want to reset the selected value from outside the component, e.g. if there are two Select components that should be in sync, you can set the dependent Select value to null
in the onChange
handler of the first Select component.
import { useState } from 'react'; import { Select } from '@grafana/ui'; const SelectComponent = () => { const [person, setPerson] = useState<string | undefined>(''); const [team, setTeam] = useState<string | undefined | null>(''); return ( <form> <Select onChange={({ value }) => { setPerson(value); setTeam(null); // Setting the team to null will reset the selected value in the team Select }} options={[ { value: 'option1', label: 'Option 1', }, { value: 'option2', label: 'Option 2', }, ]} value={person} backspaceRemovesValue /> <Select onChange={({ value }) => setTeam(value)} options={[ { value: 'team1', label: 'Team 1', }, { value: 'team', label: 'Team 2', }, ]} value={team} /> </form> ); };
Like regular Select, but handles fetching options asynchronously. Use the loadOptions
prop for the async function that loads the options. If defaultOptions
is set to true
, loadOptions
will be called when the component is mounted.
import { AsyncSelect } from '@grafana/ui'; const basicSelectAsync = () => { const [value, setValue] = useState<SelectableValue<string>>(); return ( <AsyncSelect loadOptions={loadAsyncOptions} defaultOptions value={value} onChange={v => { setValue(v); }} /> ); };
Where the async function could look like this:
const loadAsyncOptions = () => { return new Promise<Array<SelectableValue<string>>>((resolve) => { setTimeout(() => { resolve(options); }, 2000); }); };
Possible to Select multiple values at the same time.
import { MultiSelect } from '@grafana/ui'; const multiSelect = () => { const [value, setValue] = useState<Array<SelectableValue<string>>>([]); return ( <> <MultiSelect options={options} value={value} onChange={(v) => { setValue(v); }} /> </> ); };
Like MultiSelect but handles data asynchronously with the loadOptions
prop.
Using React Testing Library, you can select the <Select />
using its matching label, such as the label assigned with the inputId
prop. Use the react-select-event
package to select values from the options.
import { render, screen } from '@testing-library/react'; import selectEvent from 'react-select-event'; import { Select } from '@grafana/ui'; it('should call onChange', () => { const onChange = jest.fn(); render( <> <label htmlFor="my-select">My select</label> <Select onChange={onChange} options={options} inputId="my-select" /> </> ); const selectEl = screen.getByLabelText('My select'); expect(selectEl).toBeInTheDocument(); await selectEvent.select(selectEl, 'Option 2', { container: document.body }); expect(onChange).toHaveBeenCalledWith({ label: 'Option 2', value: 2, }); });
Name | Description | Default |
---|---|---|
aria-label | Aria label applied to the input field string | - |
data-testid | string | - |
allowCreateWhileLoading | boolean | - |
allowCustomValue | boolean | - |
autoFocus | Focus is set to the Select when rendered boolean | - |
backspaceRemovesValue | boolean | - |
blurInputOnSelect | boolean | - |
captureMenuScroll | boolean | - |
className | string | - |
closeMenuOnSelect | boolean | - |
components | Used for custom components. For more information, see react-select any | - |
createOptionPosition | Sets the position of the createOption element in your options list. Defaults to 'last' "first""last" | - |
defaultValue | any | - |
disabled | boolean | - |
filterOption | ((option: SelectableValue<T>, searchQuery: string) => boolean) | - |
formatOptionLabel | ((item: SelectableValue<T>, formatOptionMeta: FormatOptionLabelMeta<T>) => ReactNode) | - |
formatCreateLabel | Function for formatting the text that is displayed when creating a new value ((input: string) => ReactNode) | - |
getOptionLabel | ((item: SelectableValue<T>) => ReactNode) | - |
getOptionValue | ((item: SelectableValue<T>) => T) | - |
hideSelectedOptions | boolean | - |
inputValue | string | - |
invalid | boolean | - |
isClearable | boolean | - |
id | The id to set on the SelectContainer component. To set the id for a label (with htmlFor), string | - |
isLoading | boolean | - |
isMulti | boolean | - |
inputId | The id of the search input. Use this to set a matching label with htmlFor string | - |
isOpen | boolean | - |
isSearchable | Disables the possibility to type into the input boolean | - |
showAllSelectedWhenOpen | boolean | - |
maxMenuHeight | number | - |
minMenuHeight | number | - |
maxVisibleValues | number | - |
menuPlacement | "auto""bottom""top" | - |
menuPosition | "absolute""fixed" | - |
menuShouldPortal | Setting to false will prevent the menu from portalling to the body. boolean | - |
noOptionsMessage | The message to display when no options could be found string | - |
onBlur | (() => void) | - |
onChange* | (value: SelectableValue<T>, actionMeta: ActionMeta) => void | {} | - |
onCloseMenu | (() => void) | - |
onCreateOption | allowCustomValue must be enabled. Function decides what to do with that custom value. ((value: string) => void) | - |
onInputChange | ((value: string, actionMeta: InputActionMeta) => void) | - |
onKeyDown | ((event: KeyboardEvent<Element>) => void) | - |
onMenuScrollToBottom | Callback which fires when the user scrolls to the bottom of the menu ((event: WheelEvent | TouchEvent) => void) | - |
onMenuScrollToTop | Callback which fires when the user scrolls to the top of the menu ((event: WheelEvent | TouchEvent) => void) | - |
onOpenMenu | (() => void) | - |
onFocus | (() => void) | - |
toggleAllOptions | { enabled: boolean; optionsFilter?: ((v: SelectableValue<T>) => boolean); determineToggleAllState?: ((selectedValues: SelectableValue<T>[], options: SelectableValue<...>[]) => ToggleAllState); } | undefined | - |
openMenuOnFocus | boolean | - |
options | SelectableValue<T>[] | - |
placeholder | string | - |
prefix | item to be rendered in front of the input stringElementnull | - |
renderControl | Use a custom element to control Select. A proper ref to the renderControl is needed if 'portal' isn't set to null ControlComponent<T> | - |
tabSelectsValue | boolean | - |
value | SelectValue<T> | null | - |
virtualized | Will wrap the MenuList in a react-window FixedSizeVirtualList for improved performance, does not support options with "description" properties boolean | - |
width | Sets the width to a multiple of 8px. Should only be used with inline forms. Setting width of the container is preferred in other cases. number"auto" | - |
isOptionDisabled | ((option: SelectableValue<T>) => boolean) | - |
isValidNewOption | allowCustomValue must be enabled. Determines whether the "create new" option should be displayed based on the current input value, select value and options array. ((inputValue: string, value: SelectableValue<T> | null, options: OptionsOrGroups<SelectableValue<T>, GroupBase<SelectableValue<T>>>) => boolean) | - |
loadingMessage | Message to display isLoading=true string | - |
noMultiValueWrap | Disables wrapping of multi value values when closed boolean | - |