@patternfly/react-core 5.0.0-alpha.62 → 5.0.0-alpha.63
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/esm/components/CalendarMonth/CalendarMonth.d.ts.map +1 -1
- package/dist/esm/components/CalendarMonth/CalendarMonth.js +9 -11
- package/dist/esm/components/CalendarMonth/CalendarMonth.js.map +1 -1
- package/dist/esm/components/DualListSelector/DualListSelectorControl.d.ts +1 -1
- package/dist/esm/components/Menu/MenuItem.d.ts +1 -1
- package/dist/esm/components/MenuToggle/MenuToggle.d.ts.map +1 -1
- package/dist/esm/components/MenuToggle/MenuToggle.js +3 -1
- package/dist/esm/components/MenuToggle/MenuToggle.js.map +1 -1
- package/dist/esm/components/Select/Select.d.ts +26 -192
- package/dist/esm/components/Select/Select.d.ts.map +1 -1
- package/dist/esm/components/Select/Select.js +51 -935
- package/dist/esm/components/Select/Select.js.map +1 -1
- package/dist/esm/components/Select/SelectGroup.d.ts +7 -8
- package/dist/esm/components/Select/SelectGroup.d.ts.map +1 -1
- package/dist/esm/components/Select/SelectGroup.js +4 -7
- package/dist/esm/components/Select/SelectGroup.js.map +1 -1
- package/dist/{js/next → esm}/components/Select/SelectList.d.ts +1 -1
- package/dist/esm/components/Select/SelectList.d.ts.map +1 -0
- package/dist/esm/{next/components → components}/Select/SelectList.js +1 -1
- package/dist/esm/components/Select/SelectList.js.map +1 -0
- package/dist/esm/components/Select/SelectOption.d.ts +13 -66
- package/dist/esm/components/Select/SelectOption.d.ts.map +1 -1
- package/dist/esm/components/Select/SelectOption.js +6 -192
- package/dist/esm/components/Select/SelectOption.js.map +1 -1
- package/dist/esm/components/Select/index.d.ts +1 -1
- package/dist/esm/components/Select/index.d.ts.map +1 -1
- package/dist/esm/components/Select/index.js +1 -1
- package/dist/esm/components/Select/index.js.map +1 -1
- package/dist/esm/deprecated/components/Select/Select.d.ts +199 -0
- package/dist/esm/deprecated/components/Select/Select.d.ts.map +1 -0
- package/dist/esm/deprecated/components/Select/Select.js +940 -0
- package/dist/esm/deprecated/components/Select/Select.js.map +1 -0
- package/dist/esm/deprecated/components/Select/SelectGroup.d.ts +13 -0
- package/dist/esm/deprecated/components/Select/SelectGroup.d.ts.map +1 -0
- package/dist/esm/deprecated/components/Select/SelectGroup.js +13 -0
- package/dist/esm/deprecated/components/Select/SelectGroup.js.map +1 -0
- package/dist/esm/deprecated/components/Select/SelectMenu.d.ts.map +1 -0
- package/dist/esm/{components → deprecated/components}/Select/SelectMenu.js +1 -1
- package/dist/esm/deprecated/components/Select/SelectMenu.js.map +1 -0
- package/dist/esm/deprecated/components/Select/SelectOption.d.ts +73 -0
- package/dist/esm/deprecated/components/Select/SelectOption.d.ts.map +1 -0
- package/dist/esm/deprecated/components/Select/SelectOption.js +196 -0
- package/dist/esm/deprecated/components/Select/SelectOption.js.map +1 -0
- package/dist/esm/deprecated/components/Select/SelectToggle.d.ts.map +1 -0
- package/dist/esm/{components → deprecated/components}/Select/SelectToggle.js +2 -2
- package/dist/esm/deprecated/components/Select/SelectToggle.js.map +1 -0
- package/dist/esm/{next → deprecated}/components/Select/index.d.ts +1 -1
- package/dist/esm/deprecated/components/Select/index.d.ts.map +1 -0
- package/dist/esm/{next → deprecated}/components/Select/index.js +1 -1
- package/dist/esm/deprecated/components/Select/index.js.map +1 -0
- package/dist/esm/deprecated/components/Select/selectConstants.d.ts.map +1 -0
- package/dist/esm/deprecated/components/Select/selectConstants.js.map +1 -0
- package/dist/esm/deprecated/components/index.d.ts +1 -0
- package/dist/esm/deprecated/components/index.d.ts.map +1 -1
- package/dist/esm/deprecated/components/index.js +1 -0
- package/dist/esm/deprecated/components/index.js.map +1 -1
- package/dist/esm/next/components/index.d.ts +0 -1
- package/dist/esm/next/components/index.d.ts.map +1 -1
- package/dist/esm/next/components/index.js +0 -1
- package/dist/esm/next/components/index.js.map +1 -1
- package/dist/js/components/CalendarMonth/CalendarMonth.d.ts.map +1 -1
- package/dist/js/components/CalendarMonth/CalendarMonth.js +8 -10
- package/dist/js/components/CalendarMonth/CalendarMonth.js.map +1 -1
- package/dist/js/components/DualListSelector/DualListSelectorControl.d.ts +1 -1
- package/dist/js/components/Menu/MenuItem.d.ts +1 -1
- package/dist/js/components/MenuToggle/MenuToggle.d.ts.map +1 -1
- package/dist/js/components/MenuToggle/MenuToggle.js +3 -1
- package/dist/js/components/MenuToggle/MenuToggle.js.map +1 -1
- package/dist/js/components/Select/Select.d.ts +26 -192
- package/dist/js/components/Select/Select.d.ts.map +1 -1
- package/dist/js/components/Select/Select.js +51 -936
- package/dist/js/components/Select/Select.js.map +1 -1
- package/dist/js/components/Select/SelectGroup.d.ts +7 -8
- package/dist/js/components/Select/SelectGroup.d.ts.map +1 -1
- package/dist/js/components/Select/SelectGroup.js +4 -7
- package/dist/js/components/Select/SelectGroup.js.map +1 -1
- package/dist/{esm/next → js}/components/Select/SelectList.d.ts +1 -1
- package/dist/js/components/Select/SelectList.d.ts.map +1 -0
- package/dist/js/{next/components → components}/Select/SelectList.js +1 -1
- package/dist/js/components/Select/SelectList.js.map +1 -0
- package/dist/js/components/Select/SelectOption.d.ts +13 -66
- package/dist/js/components/Select/SelectOption.d.ts.map +1 -1
- package/dist/js/components/Select/SelectOption.js +7 -193
- package/dist/js/components/Select/SelectOption.js.map +1 -1
- package/dist/js/components/Select/index.d.ts +1 -1
- package/dist/js/components/Select/index.d.ts.map +1 -1
- package/dist/js/components/Select/index.js +1 -1
- package/dist/js/components/Select/index.js.map +1 -1
- package/dist/js/deprecated/components/Select/Select.d.ts +199 -0
- package/dist/js/deprecated/components/Select/Select.d.ts.map +1 -0
- package/dist/js/deprecated/components/Select/Select.js +944 -0
- package/dist/js/deprecated/components/Select/Select.js.map +1 -0
- package/dist/js/deprecated/components/Select/SelectGroup.d.ts +13 -0
- package/dist/js/deprecated/components/Select/SelectGroup.d.ts.map +1 -0
- package/dist/js/deprecated/components/Select/SelectGroup.js +17 -0
- package/dist/js/deprecated/components/Select/SelectGroup.js.map +1 -0
- package/dist/js/deprecated/components/Select/SelectMenu.d.ts.map +1 -0
- package/dist/js/{components → deprecated/components}/Select/SelectMenu.js +1 -1
- package/dist/js/deprecated/components/Select/SelectMenu.js.map +1 -0
- package/dist/js/deprecated/components/Select/SelectOption.d.ts +73 -0
- package/dist/js/deprecated/components/Select/SelectOption.d.ts.map +1 -0
- package/dist/js/deprecated/components/Select/SelectOption.js +200 -0
- package/dist/js/deprecated/components/Select/SelectOption.js.map +1 -0
- package/dist/js/deprecated/components/Select/SelectToggle.d.ts.map +1 -0
- package/dist/js/{components → deprecated/components}/Select/SelectToggle.js +2 -2
- package/dist/js/deprecated/components/Select/SelectToggle.js.map +1 -0
- package/dist/js/{next → deprecated}/components/Select/index.d.ts +1 -1
- package/dist/js/deprecated/components/Select/index.d.ts.map +1 -0
- package/dist/js/{next → deprecated}/components/Select/index.js +1 -1
- package/dist/js/deprecated/components/Select/index.js.map +1 -0
- package/dist/js/deprecated/components/Select/selectConstants.d.ts.map +1 -0
- package/dist/js/deprecated/components/Select/selectConstants.js.map +1 -0
- package/dist/js/deprecated/components/index.d.ts +1 -0
- package/dist/js/deprecated/components/index.d.ts.map +1 -1
- package/dist/js/deprecated/components/index.js +1 -0
- package/dist/js/deprecated/components/index.js.map +1 -1
- package/dist/js/next/components/index.d.ts +0 -1
- package/dist/js/next/components/index.d.ts.map +1 -1
- package/dist/js/next/components/index.js +0 -1
- package/dist/js/next/components/index.js.map +1 -1
- package/dist/umd/react-core.min.js +3 -3
- package/package.json +2 -2
- package/src/components/CalendarMonth/CalendarMonth.tsx +25 -15
- package/src/components/DatePicker/__tests__/__snapshots__/DatePicker.test.tsx.snap +22 -31
- package/src/components/LoginPage/examples/LoginPageLanguageSelect.tsx +28 -19
- package/src/components/MenuToggle/MenuToggle.tsx +2 -1
- package/src/components/MenuToggle/__tests__/__snapshots__/MenuToggle.test.tsx.snap +18 -10
- package/src/components/Select/Select.tsx +113 -1475
- package/src/components/Select/SelectGroup.tsx +13 -25
- package/src/{next/components → components}/Select/SelectList.tsx +1 -1
- package/src/components/Select/SelectOption.tsx +22 -452
- package/src/components/Select/examples/Select.md +11 -2897
- package/src/{next/components → components}/Select/examples/SelectBasic.tsx +1 -2
- package/src/{next/components → components}/Select/examples/SelectCheckbox.tsx +1 -2
- package/src/{next/components → components}/Select/examples/SelectGrouped.tsx +1 -2
- package/src/{next/components → components}/Select/examples/SelectMultiTypeahead.tsx +4 -1
- package/src/{next/components → components}/Select/examples/SelectTypeahead.tsx +4 -1
- package/src/components/Select/index.ts +1 -1
- package/src/components/Toolbar/__tests__/Toolbar.test.tsx +3 -21
- package/src/components/Toolbar/__tests__/__snapshots__/Toolbar.test.tsx.snap +12 -124
- package/src/components/Toolbar/examples/Toolbar.md +0 -1
- package/src/components/Toolbar/examples/ToolbarComponentManagedToggleGroups.tsx +59 -63
- package/src/components/Toolbar/examples/ToolbarConsumerManagedToggleGroups.tsx +58 -62
- package/src/components/Toolbar/examples/ToolbarCustomChipGroupContent.tsx +107 -23
- package/src/components/Toolbar/examples/ToolbarGroups.tsx +96 -59
- package/src/components/Toolbar/examples/ToolbarStacked.tsx +56 -39
- package/src/components/Toolbar/examples/ToolbarWithFilters.tsx +115 -28
- package/src/components/Tooltip/examples/TooltipOptions.tsx +53 -23
- package/src/demos/Card/Card.md +39 -23
- package/src/demos/CardDemos.md +99 -46
- package/src/demos/Toolbar.md +51 -21
- package/src/demos/examples/Tabs/TabsAndTable.tsx +5 -22
- package/src/deprecated/components/Select/Select.tsx +1495 -0
- package/src/deprecated/components/Select/SelectGroup.tsx +36 -0
- package/src/{components → deprecated/components}/Select/SelectMenu.tsx +2 -2
- package/src/deprecated/components/Select/SelectOption.tsx +461 -0
- package/src/{components → deprecated/components}/Select/SelectToggle.tsx +3 -3
- package/src/{components → deprecated/components}/Select/__tests__/Select.test.tsx +1 -1
- package/src/deprecated/components/Select/examples/Select.md +2937 -0
- package/src/{next → deprecated}/components/Select/index.ts +1 -1
- package/src/deprecated/components/index.ts +1 -0
- package/src/next/components/index.ts +0 -1
- package/dist/esm/components/Select/SelectMenu.d.ts.map +0 -1
- package/dist/esm/components/Select/SelectMenu.js.map +0 -1
- package/dist/esm/components/Select/SelectToggle.d.ts.map +0 -1
- package/dist/esm/components/Select/SelectToggle.js.map +0 -1
- package/dist/esm/components/Select/selectConstants.d.ts.map +0 -1
- package/dist/esm/components/Select/selectConstants.js.map +0 -1
- package/dist/esm/next/components/Select/Select.d.ts +0 -33
- package/dist/esm/next/components/Select/Select.d.ts.map +0 -1
- package/dist/esm/next/components/Select/Select.js +0 -56
- package/dist/esm/next/components/Select/Select.js.map +0 -1
- package/dist/esm/next/components/Select/SelectGroup.d.ts +0 -12
- package/dist/esm/next/components/Select/SelectGroup.d.ts.map +0 -1
- package/dist/esm/next/components/Select/SelectGroup.js +0 -10
- package/dist/esm/next/components/Select/SelectGroup.js.map +0 -1
- package/dist/esm/next/components/Select/SelectList.d.ts.map +0 -1
- package/dist/esm/next/components/Select/SelectList.js.map +0 -1
- package/dist/esm/next/components/Select/SelectOption.d.ts +0 -20
- package/dist/esm/next/components/Select/SelectOption.d.ts.map +0 -1
- package/dist/esm/next/components/Select/SelectOption.js +0 -10
- package/dist/esm/next/components/Select/SelectOption.js.map +0 -1
- package/dist/esm/next/components/Select/index.d.ts.map +0 -1
- package/dist/esm/next/components/Select/index.js.map +0 -1
- package/dist/js/components/Select/SelectMenu.d.ts.map +0 -1
- package/dist/js/components/Select/SelectMenu.js.map +0 -1
- package/dist/js/components/Select/SelectToggle.d.ts.map +0 -1
- package/dist/js/components/Select/SelectToggle.js.map +0 -1
- package/dist/js/components/Select/selectConstants.d.ts.map +0 -1
- package/dist/js/components/Select/selectConstants.js.map +0 -1
- package/dist/js/next/components/Select/Select.d.ts +0 -33
- package/dist/js/next/components/Select/Select.d.ts.map +0 -1
- package/dist/js/next/components/Select/Select.js +0 -59
- package/dist/js/next/components/Select/Select.js.map +0 -1
- package/dist/js/next/components/Select/SelectGroup.d.ts +0 -12
- package/dist/js/next/components/Select/SelectGroup.d.ts.map +0 -1
- package/dist/js/next/components/Select/SelectGroup.js +0 -14
- package/dist/js/next/components/Select/SelectGroup.js.map +0 -1
- package/dist/js/next/components/Select/SelectList.d.ts.map +0 -1
- package/dist/js/next/components/Select/SelectList.js.map +0 -1
- package/dist/js/next/components/Select/SelectOption.d.ts +0 -20
- package/dist/js/next/components/Select/SelectOption.d.ts.map +0 -1
- package/dist/js/next/components/Select/SelectOption.js +0 -14
- package/dist/js/next/components/Select/SelectOption.js.map +0 -1
- package/dist/js/next/components/Select/index.d.ts.map +0 -1
- package/dist/js/next/components/Select/index.js.map +0 -1
- package/src/next/components/Select/Select.tsx +0 -133
- package/src/next/components/Select/SelectGroup.tsx +0 -24
- package/src/next/components/Select/SelectOption.tsx +0 -31
- package/src/next/components/Select/examples/Select.md +0 -38
- /package/dist/esm/{components → deprecated/components}/Select/SelectMenu.d.ts +0 -0
- /package/dist/esm/{components → deprecated/components}/Select/SelectToggle.d.ts +0 -0
- /package/dist/esm/{components → deprecated/components}/Select/selectConstants.d.ts +0 -0
- /package/dist/esm/{components → deprecated/components}/Select/selectConstants.js +0 -0
- /package/dist/js/{components → deprecated/components}/Select/SelectMenu.d.ts +0 -0
- /package/dist/js/{components → deprecated/components}/Select/SelectToggle.d.ts +0 -0
- /package/dist/js/{components → deprecated/components}/Select/selectConstants.d.ts +0 -0
- /package/dist/js/{components → deprecated/components}/Select/selectConstants.js +0 -0
- /package/src/{components → deprecated/components}/Select/__tests__/SelectGroup.test.tsx +0 -0
- /package/src/{components → deprecated/components}/Select/__tests__/SelectOption.test.tsx +0 -0
- /package/src/{components → deprecated/components}/Select/__tests__/SelectToggle.test.tsx +0 -0
- /package/src/{components → deprecated/components}/Select/__tests__/__snapshots__/Select.test.tsx.snap +0 -0
- /package/src/{components → deprecated/components}/Select/__tests__/__snapshots__/SelectGroup.test.tsx.snap +0 -0
- /package/src/{components → deprecated/components}/Select/__tests__/__snapshots__/SelectOption.test.tsx.snap +0 -0
- /package/src/{components → deprecated/components}/Select/__tests__/__snapshots__/SelectToggle.test.tsx.snap +0 -0
- /package/src/{components → deprecated/components}/Select/selectConstants.tsx +0 -0
|
@@ -3,2921 +3,35 @@ id: Select
|
|
|
3
3
|
section: components
|
|
4
4
|
subsection: menus
|
|
5
5
|
cssPrefix: pf-c-select
|
|
6
|
-
propComponents: ['Select', 'SelectOption', 'SelectGroup', '
|
|
6
|
+
propComponents: ['Select', 'SelectOption', 'SelectGroup', 'SelectList', 'MenuToggle']
|
|
7
7
|
ouia: true
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
-
import
|
|
10
|
+
import TimesIcon from '@patternfly/react-icons/dist/esm/icons/times-icon';
|
|
11
11
|
|
|
12
12
|
## Examples
|
|
13
13
|
|
|
14
|
-
### Single
|
|
14
|
+
### Single
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
A select list may use other properties for additional customization. Select each checkbox in the example below to visualize the following behavior:
|
|
19
|
-
|
|
20
|
-
- To prevent a toggle click from opening a select list, use the `isDisabled` property.
|
|
21
|
-
- To adjust the direction a select menu opens, use the `direction` property. The menu in the following example expands upwards. By default, select lists open upwards.
|
|
22
|
-
- To add an icon to a select toggle, use the `toggleIcon` property.
|
|
23
|
-
|
|
24
|
-
```js
|
|
25
|
-
import React from 'react';
|
|
26
|
-
import CubeIcon from '@patternfly/react-icons/dist/esm/icons/cube-icon';
|
|
27
|
-
import { Select, SelectOption, SelectVariant, SelectDirection, Checkbox, Divider } from '@patternfly/react-core';
|
|
28
|
-
|
|
29
|
-
class SingleSelectInput extends React.Component {
|
|
30
|
-
constructor(props) {
|
|
31
|
-
super(props);
|
|
32
|
-
this.options = [
|
|
33
|
-
<SelectOption key={0} value="Select a title" isPlaceholder />,
|
|
34
|
-
<SelectOption key={1} value="Mr" />,
|
|
35
|
-
<SelectOption key={2} value="Miss" />,
|
|
36
|
-
<SelectOption key={3} value="Mrs" />,
|
|
37
|
-
<SelectOption key={4} value="Ms" />,
|
|
38
|
-
<Divider component="li" key={5} />,
|
|
39
|
-
<SelectOption key={6} value="Dr" />,
|
|
40
|
-
<SelectOption key={7} value="Other" />
|
|
41
|
-
];
|
|
42
|
-
|
|
43
|
-
this.toggleRef = React.createRef();
|
|
44
|
-
|
|
45
|
-
this.state = {
|
|
46
|
-
isToggleIcon: false,
|
|
47
|
-
isOpen: false,
|
|
48
|
-
selected: null,
|
|
49
|
-
isDisabled: false,
|
|
50
|
-
direction: SelectDirection.down
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
this.onToggle = (_event, isOpen) => {
|
|
54
|
-
this.setState({
|
|
55
|
-
isOpen
|
|
56
|
-
});
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
this.onSelect = (event, selection, isPlaceholder) => {
|
|
60
|
-
if (isPlaceholder) this.clearSelection();
|
|
61
|
-
else {
|
|
62
|
-
this.setState({
|
|
63
|
-
selected: selection,
|
|
64
|
-
isOpen: false
|
|
65
|
-
});
|
|
66
|
-
console.log('selected:', selection);
|
|
67
|
-
this.toggleRef.current.focus();
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
this.clearSelection = () => {
|
|
72
|
-
this.setState({
|
|
73
|
-
selected: null,
|
|
74
|
-
isOpen: false
|
|
75
|
-
});
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
this.toggleDisabled = checked => {
|
|
79
|
-
this.setState({
|
|
80
|
-
isDisabled: checked
|
|
81
|
-
});
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
this.setIcon = checked => {
|
|
85
|
-
this.setState({
|
|
86
|
-
isToggleIcon: checked
|
|
87
|
-
});
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
this.toggleDirection = () => {
|
|
91
|
-
if (this.state.direction === SelectDirection.up) {
|
|
92
|
-
this.setState({
|
|
93
|
-
direction: SelectDirection.down
|
|
94
|
-
});
|
|
95
|
-
} else {
|
|
96
|
-
this.setState({
|
|
97
|
-
direction: SelectDirection.up
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
render() {
|
|
104
|
-
const { isOpen, selected, isDisabled, direction, isToggleIcon } = this.state;
|
|
105
|
-
const titleId = 'title-id-1';
|
|
106
|
-
return (
|
|
107
|
-
<div>
|
|
108
|
-
<span id={titleId} hidden>
|
|
109
|
-
Title
|
|
110
|
-
</span>
|
|
111
|
-
<Select
|
|
112
|
-
toggleRef={this.toggleRef}
|
|
113
|
-
toggleIcon={isToggleIcon && <CubeIcon />}
|
|
114
|
-
variant={SelectVariant.single}
|
|
115
|
-
aria-label="Select Input"
|
|
116
|
-
onToggle={this.onToggle}
|
|
117
|
-
onSelect={this.onSelect}
|
|
118
|
-
selections={selected}
|
|
119
|
-
isOpen={isOpen}
|
|
120
|
-
aria-labelledby={titleId}
|
|
121
|
-
isDisabled={isDisabled}
|
|
122
|
-
direction={direction}
|
|
123
|
-
ouiaId="SingleSelect"
|
|
124
|
-
>
|
|
125
|
-
{this.options}
|
|
126
|
-
</Select>
|
|
127
|
-
<Checkbox
|
|
128
|
-
label="isDisabled"
|
|
129
|
-
isChecked={this.state.isDisabled}
|
|
130
|
-
onChange={(_event, checked) => this.toggleDisabled(checked)}
|
|
131
|
-
aria-label="disabled checkbox"
|
|
132
|
-
id="toggle-disabled"
|
|
133
|
-
name="toggle-disabled"
|
|
134
|
-
/>
|
|
135
|
-
<Checkbox
|
|
136
|
-
label="Expands up"
|
|
137
|
-
isChecked={direction === SelectDirection.up}
|
|
138
|
-
onChange={this.toggleDirection}
|
|
139
|
-
aria-label="direction checkbox"
|
|
140
|
-
id="toggle-direction"
|
|
141
|
-
name="toggle-direction"
|
|
142
|
-
/>
|
|
143
|
-
<Checkbox
|
|
144
|
-
label="Show icon"
|
|
145
|
-
isChecked={isToggleIcon}
|
|
146
|
-
onChange={(_event, checked) => this.setIcon(checked)}
|
|
147
|
-
aria-label="show icon checkbox"
|
|
148
|
-
id="toggle-icon"
|
|
149
|
-
name="toggle-icon"
|
|
150
|
-
/>
|
|
151
|
-
</div>
|
|
152
|
-
);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
### With item descriptions
|
|
158
|
-
|
|
159
|
-
To give more context to a `<SelectOption>` in a list, use the `description` property.
|
|
160
|
-
|
|
161
|
-
```js
|
|
162
|
-
import React from 'react';
|
|
163
|
-
import { Select, SelectOption, SelectVariant } from '@patternfly/react-core';
|
|
164
|
-
|
|
165
|
-
class SingleSelectDescription extends React.Component {
|
|
166
|
-
constructor(props) {
|
|
167
|
-
super(props);
|
|
168
|
-
this.options = [
|
|
169
|
-
{ value: 'Mr', disabled: false },
|
|
170
|
-
{ value: 'Miss', disabled: false },
|
|
171
|
-
{ value: 'Mrs', disabled: false },
|
|
172
|
-
{ value: 'Ms', disabled: false },
|
|
173
|
-
{ value: 'Dr', disabled: false },
|
|
174
|
-
{ value: 'Other', disabled: false }
|
|
175
|
-
];
|
|
176
|
-
|
|
177
|
-
this.toggleRef = React.createRef();
|
|
178
|
-
|
|
179
|
-
this.state = {
|
|
180
|
-
isOpen: false,
|
|
181
|
-
selected: null,
|
|
182
|
-
isDisabled: false
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
this.onToggle = (_event, isOpen) => {
|
|
186
|
-
this.setState({
|
|
187
|
-
isOpen
|
|
188
|
-
});
|
|
189
|
-
};
|
|
190
|
-
|
|
191
|
-
this.onSelect = (event, selection, isPlaceholder) => {
|
|
192
|
-
if (isPlaceholder) this.clearSelection();
|
|
193
|
-
else {
|
|
194
|
-
this.setState({
|
|
195
|
-
selected: selection,
|
|
196
|
-
isOpen: false
|
|
197
|
-
});
|
|
198
|
-
console.log('selected:', selection);
|
|
199
|
-
this.toggleRef.current.focus();
|
|
200
|
-
}
|
|
201
|
-
};
|
|
202
|
-
|
|
203
|
-
this.clearSelection = () => {
|
|
204
|
-
this.setState({
|
|
205
|
-
selected: null,
|
|
206
|
-
isOpen: false
|
|
207
|
-
});
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
render() {
|
|
212
|
-
const { isOpen, selected, isDisabled, direction, isToggleIcon } = this.state;
|
|
213
|
-
const titleId = 'select-descriptions-title';
|
|
214
|
-
return (
|
|
215
|
-
<div>
|
|
216
|
-
<span id={titleId} hidden>
|
|
217
|
-
Title
|
|
218
|
-
</span>
|
|
219
|
-
<Select
|
|
220
|
-
variant={SelectVariant.single}
|
|
221
|
-
placeholderText="Select an option"
|
|
222
|
-
aria-label="Select Input with descriptions"
|
|
223
|
-
onToggle={this.onToggle}
|
|
224
|
-
toggleRef={this.toggleRef}
|
|
225
|
-
onSelect={this.onSelect}
|
|
226
|
-
selections={selected}
|
|
227
|
-
isOpen={isOpen}
|
|
228
|
-
aria-labelledby={titleId}
|
|
229
|
-
isDisabled={isDisabled}
|
|
230
|
-
>
|
|
231
|
-
{this.options.map((option, index) => (
|
|
232
|
-
<SelectOption
|
|
233
|
-
isDisabled={option.disabled}
|
|
234
|
-
key={index}
|
|
235
|
-
value={option.value}
|
|
236
|
-
isPlaceholder={option.isPlaceholder}
|
|
237
|
-
description="This is a description"
|
|
238
|
-
/>
|
|
239
|
-
))}
|
|
240
|
-
</Select>
|
|
241
|
-
</div>
|
|
242
|
-
);
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
### With grouped items
|
|
248
|
-
|
|
249
|
-
To group related select options together, use 1 or more `<SelectGroup>` components and title each group using the `label` property.
|
|
250
|
-
|
|
251
|
-
```js
|
|
252
|
-
import React from 'react';
|
|
253
|
-
import { Select, SelectOption, SelectVariant, SelectGroup, Divider } from '@patternfly/react-core';
|
|
254
|
-
|
|
255
|
-
class GroupedSingleSelectInput extends React.Component {
|
|
256
|
-
constructor(props) {
|
|
257
|
-
super(props);
|
|
258
|
-
this.state = {
|
|
259
|
-
isOpen: false,
|
|
260
|
-
selected: null
|
|
261
|
-
};
|
|
262
|
-
|
|
263
|
-
this.toggleRef = React.createRef();
|
|
264
|
-
|
|
265
|
-
this.onToggle = (_event, isOpen) => {
|
|
266
|
-
this.setState({
|
|
267
|
-
isOpen
|
|
268
|
-
});
|
|
269
|
-
};
|
|
270
|
-
|
|
271
|
-
this.onSelect = (event, selection) => {
|
|
272
|
-
this.setState({
|
|
273
|
-
selected: selection,
|
|
274
|
-
isOpen: false
|
|
275
|
-
});
|
|
276
|
-
this.toggleRef.current.focus();
|
|
277
|
-
};
|
|
278
|
-
|
|
279
|
-
this.clearSelection = () => {
|
|
280
|
-
this.setState({
|
|
281
|
-
selected: null
|
|
282
|
-
});
|
|
283
|
-
};
|
|
284
|
-
|
|
285
|
-
this.options = [
|
|
286
|
-
<SelectGroup label="Status" key="group1">
|
|
287
|
-
<SelectOption key={0} value="Running" />
|
|
288
|
-
<SelectOption key={1} value="Stopped" />
|
|
289
|
-
<SelectOption key={2} value="Down" />
|
|
290
|
-
<SelectOption key={3} value="Degraded" />
|
|
291
|
-
<SelectOption key={4} value="Needs maintenance" />
|
|
292
|
-
</SelectGroup>,
|
|
293
|
-
<Divider key="divider" />,
|
|
294
|
-
<SelectGroup label="Vendor names" key="group2">
|
|
295
|
-
<SelectOption key={5} value="Dell" />
|
|
296
|
-
<SelectOption key={6} value="Samsung" isDisabled />
|
|
297
|
-
<SelectOption key={7} value="Hewlett-Packard" />
|
|
298
|
-
</SelectGroup>
|
|
299
|
-
];
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
render() {
|
|
303
|
-
const { isOpen, selected } = this.state;
|
|
304
|
-
const titleId = 'grouped-single-select-id';
|
|
305
|
-
return (
|
|
306
|
-
<div>
|
|
307
|
-
<span id={titleId} hidden>
|
|
308
|
-
Grouped Checkbox Title
|
|
309
|
-
</span>
|
|
310
|
-
<Select
|
|
311
|
-
variant={SelectVariant.single}
|
|
312
|
-
toggleRef={this.toggleRef}
|
|
313
|
-
onToggle={this.onToggle}
|
|
314
|
-
onSelect={this.onSelect}
|
|
315
|
-
selections={selected}
|
|
316
|
-
isOpen={isOpen}
|
|
317
|
-
placeholderText="Filter by status/vendor"
|
|
318
|
-
aria-labelledby={titleId}
|
|
319
|
-
isGrouped
|
|
320
|
-
>
|
|
321
|
-
{this.options}
|
|
322
|
-
</Select>
|
|
323
|
-
</div>
|
|
324
|
-
);
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
### Favoriting items
|
|
330
|
-
|
|
331
|
-
To allow users to favorite items in a select list, use the `onFavorite` callback. When users click the favorite button, the item is duplicated and placed in a separated group at the top of the menu. To change the name of the group use the `favoritesLabel` property.
|
|
332
|
-
|
|
333
|
-
```js
|
|
334
|
-
import React from 'react';
|
|
335
|
-
import { Select, SelectOption, SelectVariant, SelectGroup } from '@patternfly/react-core';
|
|
336
|
-
|
|
337
|
-
class FavoritesSelect extends React.Component {
|
|
338
|
-
constructor(props) {
|
|
339
|
-
super(props);
|
|
340
|
-
this.state = {
|
|
341
|
-
isOpen: false,
|
|
342
|
-
selected: null,
|
|
343
|
-
favorites: []
|
|
344
|
-
};
|
|
345
|
-
|
|
346
|
-
this.onToggle = (_event, isOpen) => {
|
|
347
|
-
this.setState({
|
|
348
|
-
isOpen
|
|
349
|
-
});
|
|
350
|
-
};
|
|
351
|
-
|
|
352
|
-
this.onSelect = (event, selection, isPlaceholder) => {
|
|
353
|
-
if (isPlaceholder) this.clearSelection();
|
|
354
|
-
else {
|
|
355
|
-
this.setState({
|
|
356
|
-
selected: selection,
|
|
357
|
-
isOpen: false
|
|
358
|
-
});
|
|
359
|
-
console.log('selected:', selection);
|
|
360
|
-
}
|
|
361
|
-
};
|
|
362
|
-
|
|
363
|
-
this.clearSelection = () => {
|
|
364
|
-
this.setState({
|
|
365
|
-
selected: null,
|
|
366
|
-
isOpen: false
|
|
367
|
-
});
|
|
368
|
-
};
|
|
369
|
-
|
|
370
|
-
this.onFavorite = (itemId, isFavorite) => {
|
|
371
|
-
if (isFavorite) {
|
|
372
|
-
this.setState({
|
|
373
|
-
favorites: this.state.favorites.filter(id => id !== itemId)
|
|
374
|
-
});
|
|
375
|
-
} else
|
|
376
|
-
this.setState({
|
|
377
|
-
favorites: [...this.state.favorites, itemId]
|
|
378
|
-
});
|
|
379
|
-
};
|
|
380
|
-
|
|
381
|
-
this.options = [
|
|
382
|
-
<SelectGroup label="Status" key="group1">
|
|
383
|
-
<SelectOption id={'option-1'} key={0} value="Running" description="This is a description." />
|
|
384
|
-
<SelectOption id={'option-2'} key={1} value="Stopped" />
|
|
385
|
-
<SelectOption id={'option-3'} key={2} value="Down (disabled)" isDisabled />
|
|
386
|
-
<SelectOption id={'option-4'} key={3} value="Degraded" />
|
|
387
|
-
<SelectOption id={'option-5'} key={4} value="Needs maintenance" />
|
|
388
|
-
</SelectGroup>,
|
|
389
|
-
<SelectGroup label="Vendor names" key="group2">
|
|
390
|
-
<SelectOption id={'option-6'} key={5} value="Dell" />
|
|
391
|
-
<SelectOption id={'option-7'} key={6} value="Samsung" description="This is a description." />
|
|
392
|
-
<SelectOption id={'option-8'} key={7} value="Hewlett-Packard" />
|
|
393
|
-
</SelectGroup>
|
|
394
|
-
];
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
render() {
|
|
398
|
-
const { isOpen, selected, favorites } = this.state;
|
|
399
|
-
const titleId = 'grouped-single-select-id';
|
|
400
|
-
return (
|
|
401
|
-
<Select
|
|
402
|
-
variant={SelectVariant.typeahead}
|
|
403
|
-
typeAheadAriaLabel="Select value"
|
|
404
|
-
onToggle={this.onToggle}
|
|
405
|
-
onSelect={this.onSelect}
|
|
406
|
-
selections={selected}
|
|
407
|
-
isOpen={isOpen}
|
|
408
|
-
placeholderText="Favorites"
|
|
409
|
-
aria-labelledby={titleId}
|
|
410
|
-
isGrouped
|
|
411
|
-
onFavorite={this.onFavorite}
|
|
412
|
-
favorites={favorites}
|
|
413
|
-
onClear={this.clearSelection}
|
|
414
|
-
>
|
|
415
|
-
{this.options}
|
|
416
|
-
</Select>
|
|
417
|
-
);
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
```
|
|
421
|
-
|
|
422
|
-
### Validated selections
|
|
423
|
-
|
|
424
|
-
To validate selections that users make, pass a validation state to the `validated` property. Validating selections can let users know if the selections they make would cause issues or errors.
|
|
425
|
-
|
|
426
|
-
The example below passes an "error" state when you choose “select a title”, a "warning" state when you choose "other", and a "success" state for any other item selected from the menu.
|
|
427
|
-
|
|
428
|
-
```js
|
|
429
|
-
import React from 'react';
|
|
430
|
-
import { Select, SelectOption, SelectVariant } from '@patternfly/react-core';
|
|
431
|
-
|
|
432
|
-
class ValidatedSelect extends React.Component {
|
|
433
|
-
constructor(props) {
|
|
434
|
-
super(props);
|
|
435
|
-
this.options = [
|
|
436
|
-
<SelectOption key={0} value="Select a title" isPlaceholder />,
|
|
437
|
-
<SelectOption key={1} value="Mr" />,
|
|
438
|
-
<SelectOption key={2} value="Miss" />,
|
|
439
|
-
<SelectOption key={3} value="Mrs" />,
|
|
440
|
-
<SelectOption key={4} value="Ms" />,
|
|
441
|
-
<SelectOption key={5} value="Dr" />,
|
|
442
|
-
<SelectOption key={6} value="Other" />
|
|
443
|
-
];
|
|
444
|
-
|
|
445
|
-
this.toggleRef = React.createRef();
|
|
446
|
-
|
|
447
|
-
this.state = {
|
|
448
|
-
isOpen: false,
|
|
449
|
-
selected: null,
|
|
450
|
-
isDisabled: false,
|
|
451
|
-
validated: 'default'
|
|
452
|
-
};
|
|
453
|
-
|
|
454
|
-
this.onToggle = (_event, isOpen) => {
|
|
455
|
-
this.setState({
|
|
456
|
-
isOpen
|
|
457
|
-
});
|
|
458
|
-
};
|
|
459
|
-
|
|
460
|
-
this.onSelect = (event, selection, isPlaceholder) => {
|
|
461
|
-
let validatedState = 'success';
|
|
462
|
-
if (isPlaceholder) {
|
|
463
|
-
this.clearSelection();
|
|
464
|
-
validatedState = 'error';
|
|
465
|
-
} else {
|
|
466
|
-
if (selection === 'Other') {
|
|
467
|
-
validatedState = 'warning';
|
|
468
|
-
} else {
|
|
469
|
-
validatedState = 'success';
|
|
470
|
-
}
|
|
471
|
-
this.setState({
|
|
472
|
-
selected: selection,
|
|
473
|
-
isOpen: false
|
|
474
|
-
});
|
|
475
|
-
console.log('selected:', selection);
|
|
476
|
-
}
|
|
477
|
-
this.setState({
|
|
478
|
-
validated: validatedState
|
|
479
|
-
});
|
|
480
|
-
this.toggleRef.current.focus();
|
|
481
|
-
};
|
|
482
|
-
|
|
483
|
-
this.clearSelection = () => {
|
|
484
|
-
this.setState({
|
|
485
|
-
selected: null,
|
|
486
|
-
isOpen: false
|
|
487
|
-
});
|
|
488
|
-
};
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
render() {
|
|
492
|
-
const { isOpen, selected, isDisabled, direction, isToggleIcon, validated } = this.state;
|
|
493
|
-
const titleId = 'select-validated-title';
|
|
494
|
-
return (
|
|
495
|
-
<div>
|
|
496
|
-
<span id={titleId} hidden>
|
|
497
|
-
Title
|
|
498
|
-
</span>
|
|
499
|
-
<Select
|
|
500
|
-
variant={SelectVariant.single}
|
|
501
|
-
toggleRef={this.toggleRef}
|
|
502
|
-
placeholderText="Select an option"
|
|
503
|
-
aria-label="Select Input with validation"
|
|
504
|
-
onToggle={this.onToggle}
|
|
505
|
-
onSelect={this.onSelect}
|
|
506
|
-
selections={selected}
|
|
507
|
-
isOpen={isOpen}
|
|
508
|
-
aria-labelledby={titleId}
|
|
509
|
-
isDisabled={isDisabled}
|
|
510
|
-
validated={validated}
|
|
511
|
-
aria-describedby="validated-helper"
|
|
512
|
-
aria-invalid={validated === 'error' ? true : false}
|
|
513
|
-
>
|
|
514
|
-
{this.options}
|
|
515
|
-
</Select>
|
|
516
|
-
<div aria-live="polite" id="validated-helper" hidden>
|
|
517
|
-
{validated}
|
|
518
|
-
</div>
|
|
519
|
-
</div>
|
|
520
|
-
);
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
```
|
|
524
|
-
|
|
525
|
-
### Styled placeholder text
|
|
526
|
-
|
|
527
|
-
To add a toggle label to a select, use the `placeholderText` property. The following example displays "Filter by status" in the toggle before a selection is made.
|
|
528
|
-
|
|
529
|
-
To fade the color of `placeholderText` to gray, use the `hasPlaceholderStyle` property.
|
|
530
|
-
|
|
531
|
-
```js
|
|
532
|
-
import React from 'react';
|
|
533
|
-
import { Select, SelectOption, SelectVariant } from '@patternfly/react-core';
|
|
534
|
-
|
|
535
|
-
function SelectWithPlaceholderStyle() {
|
|
536
|
-
const [isOpen, setIsOpen] = React.useState(false);
|
|
537
|
-
const [selected, setSelected] = React.useState([]);
|
|
538
|
-
|
|
539
|
-
const options = [
|
|
540
|
-
<SelectOption key={0} value="Active" />,
|
|
541
|
-
<SelectOption key={1} value="Cancelled" />,
|
|
542
|
-
<SelectOption key={2} value="Paused" />
|
|
543
|
-
];
|
|
544
|
-
|
|
545
|
-
const onToggle = (_event, isOpen) => setIsOpen(isOpen);
|
|
546
|
-
|
|
547
|
-
const onSelect = (event, selection, isPlaceholder) => {
|
|
548
|
-
setSelected(selection);
|
|
549
|
-
setIsOpen(false);
|
|
550
|
-
};
|
|
551
|
-
|
|
552
|
-
const clearSelection = () => {
|
|
553
|
-
setSelected(null);
|
|
554
|
-
setIsOpen(false);
|
|
555
|
-
};
|
|
556
|
-
|
|
557
|
-
const titleId = 'placeholder-style-select-id';
|
|
558
|
-
|
|
559
|
-
return (
|
|
560
|
-
<div>
|
|
561
|
-
<span id={titleId} hidden>
|
|
562
|
-
Placeholder styles
|
|
563
|
-
</span>
|
|
564
|
-
<Select
|
|
565
|
-
variant={SelectVariant.single}
|
|
566
|
-
hasPlaceholderStyle
|
|
567
|
-
aria-label="Select input"
|
|
568
|
-
onToggle={onToggle}
|
|
569
|
-
onSelect={onSelect}
|
|
570
|
-
onClear={clearSelection}
|
|
571
|
-
selections={selected}
|
|
572
|
-
isOpen={isOpen}
|
|
573
|
-
placeholderText="Filter by status"
|
|
574
|
-
aria-labelledby={titleId}
|
|
575
|
-
>
|
|
576
|
-
{options}
|
|
577
|
-
</Select>
|
|
578
|
-
</div>
|
|
579
|
-
);
|
|
580
|
-
}
|
|
581
|
-
```
|
|
582
|
-
|
|
583
|
-
### Placeholder select options
|
|
584
|
-
|
|
585
|
-
To set a `<SelectOption>` as a placeholder, use the `isPlaceholder` property. The following example sets the "Filter by status" as a placeholder so that it is pre-selected.
|
|
586
|
-
|
|
587
|
-
```js
|
|
588
|
-
|
|
589
|
-
import React from 'react';
|
|
590
|
-
import { Select, SelectOption, SelectVariant } from '@patternfly/react-core';
|
|
591
|
-
|
|
592
|
-
function SelectWithPlaceholderStyle() {
|
|
593
|
-
const [isOpen, setIsOpen] = React.useState(false);
|
|
594
|
-
const [selected, setSelected] = React.useState([]);
|
|
595
|
-
|
|
596
|
-
const options = [
|
|
597
|
-
<SelectOption key={0} value="Filter by status" isPlaceholder />,
|
|
598
|
-
<SelectOption key={1} value="Active" />,
|
|
599
|
-
<SelectOption key={2} value="Cancelled" />,
|
|
600
|
-
<SelectOption key={3} value="Paused" />
|
|
601
|
-
];
|
|
602
|
-
|
|
603
|
-
const onToggle = (_event, isOpen) => setIsOpen(isOpen);
|
|
604
|
-
|
|
605
|
-
const onSelect = (event, selection, isPlaceholder) => {
|
|
606
|
-
setSelected(selection);
|
|
607
|
-
setIsOpen(false);
|
|
608
|
-
};
|
|
609
|
-
|
|
610
|
-
const clearSelection = () => {
|
|
611
|
-
setSelected(null);
|
|
612
|
-
setIsOpen(false);
|
|
613
|
-
};
|
|
614
|
-
|
|
615
|
-
const titleId = 'placeholder-style-select-option-id';
|
|
616
|
-
|
|
617
|
-
return (
|
|
618
|
-
<div>
|
|
619
|
-
<span id={titleId} hidden>
|
|
620
|
-
Placeholder styles - select option
|
|
621
|
-
</span>
|
|
622
|
-
<Select
|
|
623
|
-
variant={SelectVariant.single}
|
|
624
|
-
hasPlaceholderStyle
|
|
625
|
-
aria-label="Select input"
|
|
626
|
-
onToggle={onToggle}
|
|
627
|
-
onSelect={onSelect}
|
|
628
|
-
onClear={clearSelection}
|
|
629
|
-
selections={selected}
|
|
630
|
-
isOpen={isOpen}
|
|
631
|
-
aria-labelledby={titleId}
|
|
632
|
-
>
|
|
633
|
-
{options}
|
|
634
|
-
</Select>
|
|
635
|
-
</div>
|
|
636
|
-
);
|
|
637
|
-
}
|
|
638
|
-
```
|
|
639
|
-
|
|
640
|
-
### With a footer
|
|
641
|
-
|
|
642
|
-
You can add a `footer` to a `<Select>` list to hold actions that users can take on menu items.
|
|
643
|
-
|
|
644
|
-
```js
|
|
645
|
-
import React from 'react';
|
|
646
|
-
import CubeIcon from '@patternfly/react-icons/dist/esm/icons/cube-icon';
|
|
647
|
-
import { Select, SelectOption, SelectVariant, SelectDirection, Divider, Button } from '@patternfly/react-core';
|
|
648
|
-
|
|
649
|
-
class SelectWithFooter extends React.Component {
|
|
650
|
-
constructor(props) {
|
|
651
|
-
super(props);
|
|
652
|
-
this.options = [
|
|
653
|
-
<SelectOption key={0} value="Select a title" isPlaceholder />,
|
|
654
|
-
<SelectOption key={1} value="Mr" />,
|
|
655
|
-
<SelectOption key={2} value="Miss" />,
|
|
656
|
-
<SelectOption key={3} value="Mrs" />,
|
|
657
|
-
<SelectOption key={4} value="Ms" />,
|
|
658
|
-
<Divider component="li" key={5} />,
|
|
659
|
-
<SelectOption key={6} value="Dr" />,
|
|
660
|
-
<SelectOption key={7} value="Other" />
|
|
661
|
-
];
|
|
662
|
-
|
|
663
|
-
this.toggleRef = React.createRef();
|
|
664
|
-
|
|
665
|
-
this.state = {
|
|
666
|
-
isToggleIcon: false,
|
|
667
|
-
isOpen: false,
|
|
668
|
-
selected: null,
|
|
669
|
-
isDisabled: false,
|
|
670
|
-
direction: SelectDirection.down
|
|
671
|
-
};
|
|
672
|
-
|
|
673
|
-
this.onToggle = (_event, isOpen) => {
|
|
674
|
-
this.setState({
|
|
675
|
-
isOpen
|
|
676
|
-
});
|
|
677
|
-
};
|
|
678
|
-
|
|
679
|
-
this.onSelect = (event, selection, isPlaceholder) => {
|
|
680
|
-
if (isPlaceholder) this.clearSelection();
|
|
681
|
-
else {
|
|
682
|
-
this.setState({
|
|
683
|
-
selected: selection,
|
|
684
|
-
isOpen: false
|
|
685
|
-
});
|
|
686
|
-
console.log('selected:', selection);
|
|
687
|
-
this.toggleRef.current.focus();
|
|
688
|
-
}
|
|
689
|
-
};
|
|
690
|
-
|
|
691
|
-
this.clearSelection = () => {
|
|
692
|
-
this.setState({
|
|
693
|
-
selected: null,
|
|
694
|
-
isOpen: false
|
|
695
|
-
});
|
|
696
|
-
};
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
render() {
|
|
700
|
-
const { isOpen, selected, isDisabled, direction, isToggleIcon } = this.state;
|
|
701
|
-
const titleId = 'title-id-footer';
|
|
702
|
-
return (
|
|
703
|
-
<div>
|
|
704
|
-
<span id={titleId} hidden>
|
|
705
|
-
Title
|
|
706
|
-
</span>
|
|
707
|
-
<Select
|
|
708
|
-
toggleIcon={isToggleIcon && <CubeIcon />}
|
|
709
|
-
toggleRef={this.toggleRef}
|
|
710
|
-
variant={SelectVariant.single}
|
|
711
|
-
aria-label="Select Input"
|
|
712
|
-
onToggle={this.onToggle}
|
|
713
|
-
onSelect={this.onSelect}
|
|
714
|
-
selections={selected}
|
|
715
|
-
isOpen={isOpen}
|
|
716
|
-
aria-labelledby={titleId}
|
|
717
|
-
isDisabled={isDisabled}
|
|
718
|
-
direction={direction}
|
|
719
|
-
footer={
|
|
720
|
-
<>
|
|
721
|
-
<Button variant="link" isInline>
|
|
722
|
-
Action
|
|
723
|
-
</Button>
|
|
724
|
-
</>
|
|
725
|
-
}
|
|
726
|
-
>
|
|
727
|
-
{this.options}
|
|
728
|
-
</Select>
|
|
729
|
-
</div>
|
|
730
|
-
);
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
```
|
|
734
|
-
|
|
735
|
-
### With view more
|
|
736
|
-
|
|
737
|
-
To reduce the processing load for long select lists, replace overflow items with a "View more" link at the bottom of the select menu.
|
|
738
|
-
|
|
739
|
-
Adjust the number of items shown above the "View more" link with the `numOptions` property. The following example passes 3 items into this property.
|
|
740
|
-
|
|
741
|
-
```js
|
|
742
|
-
import React from 'react';
|
|
743
|
-
import { Select, SelectOption, SelectVariant } from '@patternfly/react-core';
|
|
744
|
-
|
|
745
|
-
class SelectViewMore extends React.Component {
|
|
746
|
-
constructor(props) {
|
|
747
|
-
super(props);
|
|
748
|
-
this.options = [
|
|
749
|
-
<SelectOption key={0} value="Select a title" isPlaceholder />,
|
|
750
|
-
<SelectOption key={1} value="Mr" />,
|
|
751
|
-
<SelectOption key={2} value="Miss" />,
|
|
752
|
-
<SelectOption key={3} value="Mrs" />,
|
|
753
|
-
<SelectOption key={4} value="Ms" />,
|
|
754
|
-
<SelectOption key={5} value="Dr" />,
|
|
755
|
-
<SelectOption key={6} value="Other" />
|
|
756
|
-
];
|
|
757
|
-
|
|
758
|
-
this.toggleRef = React.createRef();
|
|
759
|
-
|
|
760
|
-
this.state = {
|
|
761
|
-
isOpen: false,
|
|
762
|
-
selected: null,
|
|
763
|
-
numOptions: 3,
|
|
764
|
-
isLoading: false
|
|
765
|
-
};
|
|
766
|
-
|
|
767
|
-
this.onToggle = (_event, isOpen) => {
|
|
768
|
-
this.setState({
|
|
769
|
-
isOpen
|
|
770
|
-
});
|
|
771
|
-
};
|
|
772
|
-
|
|
773
|
-
this.onSelect = (event, selection, isPlaceholder) => {
|
|
774
|
-
if (isPlaceholder) this.clearSelection();
|
|
775
|
-
else {
|
|
776
|
-
this.setState({
|
|
777
|
-
selected: selection,
|
|
778
|
-
isOpen: false
|
|
779
|
-
});
|
|
780
|
-
console.log('selected:', selection);
|
|
781
|
-
this.toggleRef.current.focus();
|
|
782
|
-
}
|
|
783
|
-
};
|
|
784
|
-
|
|
785
|
-
this.clearSelection = () => {
|
|
786
|
-
this.setState({
|
|
787
|
-
selected: null,
|
|
788
|
-
isOpen: false
|
|
789
|
-
});
|
|
790
|
-
};
|
|
791
|
-
|
|
792
|
-
this.simulateNetworkCall = callback => {
|
|
793
|
-
setTimeout(callback, 2000);
|
|
794
|
-
};
|
|
795
|
-
|
|
796
|
-
this.onViewMoreClick = () => {
|
|
797
|
-
// Set select loadingVariant to spinner then simulate network call before loading more options
|
|
798
|
-
this.setState({ isLoading: true });
|
|
799
|
-
this.simulateNetworkCall(() => {
|
|
800
|
-
const newLength =
|
|
801
|
-
this.state.numOptions + 3 <= this.options.length ? this.state.numOptions + 3 : this.options.length;
|
|
802
|
-
this.setState({ numOptions: newLength, isLoading: false });
|
|
803
|
-
});
|
|
804
|
-
};
|
|
805
|
-
}
|
|
806
|
-
|
|
807
|
-
render() {
|
|
808
|
-
const { isOpen, selected, isToggleIcon, numOptions, loadingVariant, isLoading } = this.state;
|
|
809
|
-
const titleId = 'title-id-view-more';
|
|
810
|
-
return (
|
|
811
|
-
<div>
|
|
812
|
-
<span id={titleId} hidden>
|
|
813
|
-
Title
|
|
814
|
-
</span>
|
|
815
|
-
<Select
|
|
816
|
-
variant={SelectVariant.single}
|
|
817
|
-
toggleRef={this.toggleRef}
|
|
818
|
-
aria-label="Select Input"
|
|
819
|
-
onToggle={this.onToggle}
|
|
820
|
-
onSelect={this.onSelect}
|
|
821
|
-
selections={selected}
|
|
822
|
-
isOpen={isOpen}
|
|
823
|
-
aria-labelledby={titleId}
|
|
824
|
-
{...(!isLoading &&
|
|
825
|
-
numOptions < this.options.length && {
|
|
826
|
-
loadingVariant: { text: 'View more', onClick: this.onViewMoreClick }
|
|
827
|
-
})}
|
|
828
|
-
{...(isLoading && { loadingVariant: 'spinner' })}
|
|
829
|
-
>
|
|
830
|
-
{this.options.slice(0, numOptions)}
|
|
831
|
-
</Select>
|
|
832
|
-
</div>
|
|
833
|
-
);
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
```
|
|
837
|
-
|
|
838
|
-
### Checkbox select
|
|
839
|
-
|
|
840
|
-
To let users select multiple list options via checkbox input, use a checkbox select. To create a checkbox select, pass `variant={SelectVariant.checkbox}` into the `<Select>` component.
|
|
841
|
-
|
|
842
|
-
By default, a badge is displayed in the menu toggle that indicates the number of items a user has selected.
|
|
843
|
-
|
|
844
|
-
```js
|
|
845
|
-
import React from 'react';
|
|
846
|
-
import { Select, SelectOption, SelectVariant, Divider } from '@patternfly/react-core';
|
|
847
|
-
|
|
848
|
-
class CheckboxSelectInput extends React.Component {
|
|
849
|
-
constructor(props) {
|
|
850
|
-
super(props);
|
|
851
|
-
|
|
852
|
-
this.state = {
|
|
853
|
-
isOpen: false,
|
|
854
|
-
selected: []
|
|
855
|
-
};
|
|
856
|
-
|
|
857
|
-
this.onToggle = (_event, isOpen) => {
|
|
858
|
-
this.setState({
|
|
859
|
-
isOpen
|
|
860
|
-
});
|
|
861
|
-
};
|
|
862
|
-
|
|
863
|
-
this.onSelect = (event, selection) => {
|
|
864
|
-
const { selected } = this.state;
|
|
865
|
-
if (selected.includes(selection)) {
|
|
866
|
-
this.setState(
|
|
867
|
-
prevState => ({ selected: prevState.selected.filter(item => item !== selection) }),
|
|
868
|
-
() => console.log('selections: ', this.state.selected)
|
|
869
|
-
);
|
|
870
|
-
} else {
|
|
871
|
-
this.setState(
|
|
872
|
-
prevState => ({ selected: [...prevState.selected, selection] }),
|
|
873
|
-
() => console.log('selections: ', this.state.selected)
|
|
874
|
-
);
|
|
875
|
-
}
|
|
876
|
-
};
|
|
877
|
-
|
|
878
|
-
this.clearSelection = () => {
|
|
879
|
-
this.setState({
|
|
880
|
-
selected: []
|
|
881
|
-
});
|
|
882
|
-
};
|
|
883
|
-
|
|
884
|
-
this.options = [
|
|
885
|
-
<SelectOption key={0} value="Active" description="This is a description" />,
|
|
886
|
-
<SelectOption key={1} value="Cancelled" />,
|
|
887
|
-
<SelectOption key={2} value="Paused" />,
|
|
888
|
-
<Divider key={3} />,
|
|
889
|
-
<SelectOption key={4} value="Warning" />,
|
|
890
|
-
<SelectOption key={5} value="Restarted" />
|
|
891
|
-
];
|
|
892
|
-
}
|
|
893
|
-
|
|
894
|
-
render() {
|
|
895
|
-
const { isOpen, selected } = this.state;
|
|
896
|
-
const titleId = 'checkbox-select-id';
|
|
897
|
-
return (
|
|
898
|
-
<div>
|
|
899
|
-
<span id={titleId} hidden>
|
|
900
|
-
Checkbox Title
|
|
901
|
-
</span>
|
|
902
|
-
<Select
|
|
903
|
-
variant={SelectVariant.checkbox}
|
|
904
|
-
aria-label="Select Input"
|
|
905
|
-
onToggle={this.onToggle}
|
|
906
|
-
onSelect={this.onSelect}
|
|
907
|
-
selections={selected}
|
|
908
|
-
isOpen={isOpen}
|
|
909
|
-
placeholderText="Filter by status"
|
|
910
|
-
aria-labelledby={titleId}
|
|
911
|
-
>
|
|
912
|
-
{this.options}
|
|
913
|
-
</Select>
|
|
914
|
-
</div>
|
|
915
|
-
);
|
|
916
|
-
}
|
|
917
|
-
}
|
|
918
|
-
```
|
|
919
|
-
|
|
920
|
-
### Checkbox select with grouped items
|
|
921
|
-
|
|
922
|
-
You can use groups alongside checkbox input. The item count badge will display the number of items selected across all groups.
|
|
923
|
-
|
|
924
|
-
```js
|
|
925
|
-
import React from 'react';
|
|
926
|
-
import { Select, SelectOption, SelectVariant, SelectGroup } from '@patternfly/react-core';
|
|
927
|
-
|
|
928
|
-
class GroupedCheckboxSelectInput extends React.Component {
|
|
929
|
-
constructor(props) {
|
|
930
|
-
super(props);
|
|
931
|
-
this.state = {
|
|
932
|
-
isOpen: false,
|
|
933
|
-
selected: []
|
|
934
|
-
};
|
|
935
|
-
|
|
936
|
-
this.onToggle = (_event, isOpen) => {
|
|
937
|
-
this.setState({
|
|
938
|
-
isOpen
|
|
939
|
-
});
|
|
940
|
-
};
|
|
941
|
-
|
|
942
|
-
this.onSelect = (event, selection) => {
|
|
943
|
-
const { selected } = this.state;
|
|
944
|
-
if (selected.includes(selection)) {
|
|
945
|
-
this.setState(
|
|
946
|
-
prevState => ({ selected: prevState.selected.filter(item => item !== selection) }),
|
|
947
|
-
() => console.log('selections: ', this.state.selected)
|
|
948
|
-
);
|
|
949
|
-
} else {
|
|
950
|
-
this.setState(
|
|
951
|
-
prevState => ({ selected: [...prevState.selected, selection] }),
|
|
952
|
-
() => console.log('selections: ', this.state.selected)
|
|
953
|
-
);
|
|
954
|
-
}
|
|
955
|
-
};
|
|
956
|
-
|
|
957
|
-
this.clearSelection = () => {
|
|
958
|
-
this.setState({
|
|
959
|
-
selected: []
|
|
960
|
-
});
|
|
961
|
-
};
|
|
962
|
-
|
|
963
|
-
this.options = [
|
|
964
|
-
<SelectGroup label="Status" key="group1">
|
|
965
|
-
<SelectOption key={0} value="Running" />
|
|
966
|
-
<SelectOption key={1} value="Stopped" />
|
|
967
|
-
<SelectOption key={2} value="Down" />
|
|
968
|
-
<SelectOption key={3} value="Degraded" />
|
|
969
|
-
<SelectOption key={4} value="Needs maintenance" />
|
|
970
|
-
</SelectGroup>,
|
|
971
|
-
<SelectGroup label="Vendor names" key="group2">
|
|
972
|
-
<SelectOption key={5} value="Dell" />
|
|
973
|
-
<SelectOption key={6} value="Samsung" isDisabled />
|
|
974
|
-
<SelectOption key={7} value="Hewlett-Packard" />
|
|
975
|
-
</SelectGroup>
|
|
976
|
-
];
|
|
977
|
-
}
|
|
978
|
-
|
|
979
|
-
render() {
|
|
980
|
-
const { isOpen, selected } = this.state;
|
|
981
|
-
const titleId = 'grouped-checkbox-select-id-1';
|
|
982
|
-
return (
|
|
983
|
-
<div>
|
|
984
|
-
<span id={titleId} hidden>
|
|
985
|
-
Grouped Checkbox Title
|
|
986
|
-
</span>
|
|
987
|
-
<Select
|
|
988
|
-
variant={SelectVariant.checkbox}
|
|
989
|
-
onToggle={this.onToggle}
|
|
990
|
-
onSelect={this.onSelect}
|
|
991
|
-
selections={selected}
|
|
992
|
-
isOpen={isOpen}
|
|
993
|
-
placeholderText="Filter by status"
|
|
994
|
-
aria-labelledby={titleId}
|
|
995
|
-
isGrouped
|
|
996
|
-
>
|
|
997
|
-
{this.options}
|
|
998
|
-
</Select>
|
|
999
|
-
</div>
|
|
1000
|
-
);
|
|
1001
|
-
}
|
|
1002
|
-
}
|
|
16
|
+
```ts file="./SelectBasic.tsx"
|
|
1003
17
|
```
|
|
1004
18
|
|
|
1005
|
-
###
|
|
1006
|
-
|
|
1007
|
-
To change the default badge text for a checkbox select, use the `customBadgeText` property. The following example uses `customBadgeText` to display "all" in the badge once all menu items are selected.
|
|
1008
|
-
|
|
1009
|
-
```js
|
|
1010
|
-
import React from 'react';
|
|
1011
|
-
import { Select, SelectOption, SelectGroup, SelectVariant } from '@patternfly/react-core';
|
|
1012
|
-
|
|
1013
|
-
class FilteringCheckboxSelectInputWithBadging extends React.Component {
|
|
1014
|
-
constructor(props) {
|
|
1015
|
-
super(props);
|
|
1016
|
-
|
|
1017
|
-
this.state = {
|
|
1018
|
-
isOpen: false,
|
|
1019
|
-
selected: [],
|
|
1020
|
-
customBadgeText: 0
|
|
1021
|
-
};
|
|
1022
|
-
|
|
1023
|
-
this.options = [
|
|
1024
|
-
<SelectGroup label="Status" key="group1">
|
|
1025
|
-
<SelectOption key={0} value="Running" />
|
|
1026
|
-
<SelectOption key={1} value="Stopped" />
|
|
1027
|
-
<SelectOption key={2} value="Down" />
|
|
1028
|
-
<SelectOption key={3} value="Degraded" />
|
|
1029
|
-
<SelectOption key={4} value="Needs maintenance" />
|
|
1030
|
-
</SelectGroup>,
|
|
1031
|
-
<SelectGroup label="Vendor names" key="group2">
|
|
1032
|
-
<SelectOption key={5} value="Dell" />
|
|
1033
|
-
<SelectOption key={6} value="Samsung" isDisabled />
|
|
1034
|
-
<SelectOption key={7} value="Hewlett-Packard" />
|
|
1035
|
-
</SelectGroup>
|
|
1036
|
-
];
|
|
1037
|
-
|
|
1038
|
-
this.onToggle = (_event, isOpen) => {
|
|
1039
|
-
this.setState({
|
|
1040
|
-
isOpen
|
|
1041
|
-
});
|
|
1042
|
-
};
|
|
1043
|
-
|
|
1044
|
-
this.onSelect = (event, selection) => {
|
|
1045
|
-
const { selected } = this.state;
|
|
1046
|
-
if (selected.includes(selection)) {
|
|
1047
|
-
this.setState(
|
|
1048
|
-
prevState => ({
|
|
1049
|
-
selected: prevState.selected.filter(item => item !== selection),
|
|
1050
|
-
customBadgeText: this.setBadgeText(prevState.selected.length - 1)
|
|
1051
|
-
}),
|
|
1052
|
-
() => console.log('selections: ', this.state.selected)
|
|
1053
|
-
);
|
|
1054
|
-
} else {
|
|
1055
|
-
this.setState(
|
|
1056
|
-
prevState => ({
|
|
1057
|
-
selected: [...prevState.selected, selection],
|
|
1058
|
-
customBadgeText: this.setBadgeText(prevState.selected.length + 1)
|
|
1059
|
-
}),
|
|
1060
|
-
() => console.log('selections: ', this.state.selected)
|
|
1061
|
-
);
|
|
1062
|
-
}
|
|
1063
|
-
};
|
|
1064
|
-
|
|
1065
|
-
this.onFilter = (_, textInput) => {
|
|
1066
|
-
if (textInput === '') {
|
|
1067
|
-
return this.options;
|
|
1068
|
-
} else {
|
|
1069
|
-
let filteredGroups = this.options
|
|
1070
|
-
.map(group => {
|
|
1071
|
-
let filteredGroup = React.cloneElement(group, {
|
|
1072
|
-
children: group.props.children.filter(item => {
|
|
1073
|
-
return item.props.value.toLowerCase().includes(textInput.toLowerCase());
|
|
1074
|
-
})
|
|
1075
|
-
});
|
|
1076
|
-
if (filteredGroup.props.children.length > 0) return filteredGroup;
|
|
1077
|
-
})
|
|
1078
|
-
.filter(newGroup => newGroup);
|
|
1079
|
-
return filteredGroups;
|
|
1080
|
-
}
|
|
1081
|
-
};
|
|
1082
|
-
|
|
1083
|
-
this.clearSelection = () => {
|
|
1084
|
-
this.setState({
|
|
1085
|
-
selected: [],
|
|
1086
|
-
customBadgeText: this.setBadgeText(0)
|
|
1087
|
-
});
|
|
1088
|
-
};
|
|
1089
|
-
|
|
1090
|
-
this.setBadgeText = selected => {
|
|
1091
|
-
if (selected === 7) {
|
|
1092
|
-
return 'All';
|
|
1093
|
-
}
|
|
1094
|
-
if (selected === 0) {
|
|
1095
|
-
return 0;
|
|
1096
|
-
}
|
|
1097
|
-
return null;
|
|
1098
|
-
};
|
|
1099
|
-
}
|
|
1100
|
-
|
|
1101
|
-
render() {
|
|
1102
|
-
const { isOpen, selected, filteredOptions, customBadgeText } = this.state;
|
|
1103
|
-
const titleId = 'checkbox-filtering-custom-badging-select-id';
|
|
1104
|
-
return (
|
|
1105
|
-
<div>
|
|
1106
|
-
<span id={titleId} hidden>
|
|
1107
|
-
Checkbox Title
|
|
1108
|
-
</span>
|
|
1109
|
-
<Select
|
|
1110
|
-
variant={SelectVariant.checkbox}
|
|
1111
|
-
onToggle={this.onToggle}
|
|
1112
|
-
onSelect={this.onSelect}
|
|
1113
|
-
selections={selected}
|
|
1114
|
-
isOpen={isOpen}
|
|
1115
|
-
placeholderText="Filter by status"
|
|
1116
|
-
aria-labelledby={titleId}
|
|
1117
|
-
onFilter={this.onFilter}
|
|
1118
|
-
onClear={this.clearSelection}
|
|
1119
|
-
isGrouped
|
|
1120
|
-
hasInlineFilter
|
|
1121
|
-
customBadgeText={customBadgeText}
|
|
1122
|
-
>
|
|
1123
|
-
{this.options}
|
|
1124
|
-
</Select>
|
|
1125
|
-
</div>
|
|
1126
|
-
);
|
|
1127
|
-
}
|
|
1128
|
-
}
|
|
1129
|
-
```
|
|
1130
|
-
|
|
1131
|
-
### Checkbox select without selected count
|
|
1132
|
-
|
|
1133
|
-
To remove the default item count badge, use the `isCheckboxSelectionBadgeHidden` property.
|
|
1134
|
-
|
|
1135
|
-
```js
|
|
1136
|
-
import React from 'react';
|
|
1137
|
-
import { Select, SelectOption, SelectVariant } from '@patternfly/react-core';
|
|
1138
|
-
|
|
1139
|
-
class CheckboxSelectInputNoBadge extends React.Component {
|
|
1140
|
-
constructor(props) {
|
|
1141
|
-
super(props);
|
|
1142
|
-
|
|
1143
|
-
this.state = {
|
|
1144
|
-
isOpen: false,
|
|
1145
|
-
selected: []
|
|
1146
|
-
};
|
|
1147
|
-
|
|
1148
|
-
this.onToggle = (_event, isOpen) => {
|
|
1149
|
-
this.setState({
|
|
1150
|
-
isOpen
|
|
1151
|
-
});
|
|
1152
|
-
};
|
|
19
|
+
### Grouped single
|
|
1153
20
|
|
|
1154
|
-
|
|
1155
|
-
const { selected } = this.state;
|
|
1156
|
-
if (selected.includes(selection)) {
|
|
1157
|
-
this.setState(
|
|
1158
|
-
prevState => ({ selected: prevState.selected.filter(item => item !== selection) }),
|
|
1159
|
-
() => console.log('selections: ', this.state.selected)
|
|
1160
|
-
);
|
|
1161
|
-
} else {
|
|
1162
|
-
this.setState(
|
|
1163
|
-
prevState => ({ selected: [...prevState.selected, selection] }),
|
|
1164
|
-
() => console.log('selections: ', this.state.selected)
|
|
1165
|
-
);
|
|
1166
|
-
}
|
|
1167
|
-
};
|
|
1168
|
-
|
|
1169
|
-
this.clearSelection = () => {
|
|
1170
|
-
this.setState({
|
|
1171
|
-
selected: []
|
|
1172
|
-
});
|
|
1173
|
-
};
|
|
1174
|
-
|
|
1175
|
-
this.options = [
|
|
1176
|
-
<SelectOption key={0} value="Debug" />,
|
|
1177
|
-
<SelectOption key={1} value="Info" />,
|
|
1178
|
-
<SelectOption key={2} value="Warn" />,
|
|
1179
|
-
<SelectOption key={3} value="Error" />
|
|
1180
|
-
];
|
|
1181
|
-
}
|
|
1182
|
-
|
|
1183
|
-
render() {
|
|
1184
|
-
const { isOpen, selected } = this.state;
|
|
1185
|
-
const titleId = 'checkbox-no-badge-select-id';
|
|
1186
|
-
return (
|
|
1187
|
-
<div>
|
|
1188
|
-
<span id={titleId} hidden>
|
|
1189
|
-
Checkbox Title
|
|
1190
|
-
</span>
|
|
1191
|
-
<Select
|
|
1192
|
-
variant={SelectVariant.checkbox}
|
|
1193
|
-
aria-label="Select Input"
|
|
1194
|
-
onToggle={this.onToggle}
|
|
1195
|
-
onSelect={this.onSelect}
|
|
1196
|
-
selections={selected}
|
|
1197
|
-
isCheckboxSelectionBadgeHidden
|
|
1198
|
-
isOpen={isOpen}
|
|
1199
|
-
placeholderText="Filter by status"
|
|
1200
|
-
aria-labelledby={titleId}
|
|
1201
|
-
>
|
|
1202
|
-
{this.options}
|
|
1203
|
-
</Select>
|
|
1204
|
-
</div>
|
|
1205
|
-
);
|
|
1206
|
-
}
|
|
1207
|
-
}
|
|
21
|
+
```ts file="./SelectGrouped.tsx"
|
|
1208
22
|
```
|
|
1209
23
|
|
|
1210
|
-
### Checkbox
|
|
1211
|
-
|
|
1212
|
-
To show users the number of items that a `<SelectOption>` would match, use the `itemCount` property. The numerical value you pass into `itemCount` is displayed to the right of each menu item.
|
|
1213
|
-
|
|
1214
|
-
```js
|
|
1215
|
-
import React from 'react';
|
|
1216
|
-
import { Select, SelectOption, SelectVariant, Divider } from '@patternfly/react-core';
|
|
1217
|
-
|
|
1218
|
-
class CheckboxSelectWithCounts extends React.Component {
|
|
1219
|
-
constructor(props) {
|
|
1220
|
-
super(props);
|
|
1221
|
-
|
|
1222
|
-
this.state = {
|
|
1223
|
-
isOpen: false,
|
|
1224
|
-
selected: []
|
|
1225
|
-
};
|
|
1226
|
-
|
|
1227
|
-
this.onToggle = (_event, isOpen) => {
|
|
1228
|
-
this.setState({
|
|
1229
|
-
isOpen
|
|
1230
|
-
});
|
|
1231
|
-
};
|
|
1232
|
-
|
|
1233
|
-
this.onSelect = (event, selection) => {
|
|
1234
|
-
const { selected } = this.state;
|
|
1235
|
-
if (selected.includes(selection)) {
|
|
1236
|
-
this.setState(
|
|
1237
|
-
prevState => ({ selected: prevState.selected.filter(item => item !== selection) }),
|
|
1238
|
-
() => console.log('selections: ', this.state.selected)
|
|
1239
|
-
);
|
|
1240
|
-
} else {
|
|
1241
|
-
this.setState(
|
|
1242
|
-
prevState => ({ selected: [...prevState.selected, selection] }),
|
|
1243
|
-
() => console.log('selections: ', this.state.selected)
|
|
1244
|
-
);
|
|
1245
|
-
}
|
|
1246
|
-
};
|
|
1247
|
-
|
|
1248
|
-
this.clearSelection = () => {
|
|
1249
|
-
this.setState({
|
|
1250
|
-
selected: []
|
|
1251
|
-
});
|
|
1252
|
-
};
|
|
1253
|
-
|
|
1254
|
-
this.options = [
|
|
1255
|
-
<SelectOption key={0} value="Active" description="This is a description" itemCount={3} />,
|
|
1256
|
-
<SelectOption key={1} value="Cancelled" itemCount={1} />,
|
|
1257
|
-
<SelectOption key={2} value="Paused" itemCount={15} />,
|
|
1258
|
-
<SelectOption key={3} value="Warning" itemCount={2} />,
|
|
1259
|
-
<SelectOption key={4} value="Restarted" itemCount={8} />
|
|
1260
|
-
];
|
|
1261
|
-
}
|
|
24
|
+
### Checkbox
|
|
1262
25
|
|
|
1263
|
-
|
|
1264
|
-
const { isOpen, selected } = this.state;
|
|
1265
|
-
const titleId = 'checkbox-select-with-counts-id';
|
|
1266
|
-
return (
|
|
1267
|
-
<div>
|
|
1268
|
-
<span id={titleId} hidden>
|
|
1269
|
-
Checkbox With Counts Title
|
|
1270
|
-
</span>
|
|
1271
|
-
<Select
|
|
1272
|
-
variant={SelectVariant.checkbox}
|
|
1273
|
-
aria-label="Select Input"
|
|
1274
|
-
onToggle={this.onToggle}
|
|
1275
|
-
onSelect={this.onSelect}
|
|
1276
|
-
selections={selected}
|
|
1277
|
-
isOpen={isOpen}
|
|
1278
|
-
placeholderText="Filter by status"
|
|
1279
|
-
aria-labelledby={titleId}
|
|
1280
|
-
>
|
|
1281
|
-
{this.options}
|
|
1282
|
-
</Select>
|
|
1283
|
-
</div>
|
|
1284
|
-
);
|
|
1285
|
-
}
|
|
1286
|
-
}
|
|
1287
|
-
```
|
|
1288
|
-
|
|
1289
|
-
### Checkbox select with a footer
|
|
1290
|
-
|
|
1291
|
-
You can combine a footer with checkbox input to allow users to apply an action to multiple items.
|
|
1292
|
-
|
|
1293
|
-
```js
|
|
1294
|
-
import React from 'react';
|
|
1295
|
-
import { Select, SelectOption, SelectVariant, Button } from '@patternfly/react-core';
|
|
1296
|
-
|
|
1297
|
-
class SelectWithFooterCheckbox extends React.Component {
|
|
1298
|
-
constructor(props) {
|
|
1299
|
-
super(props);
|
|
1300
|
-
this.state = {
|
|
1301
|
-
isOpen: false,
|
|
1302
|
-
selected: [],
|
|
1303
|
-
numOptions: 3,
|
|
1304
|
-
isLoading: false
|
|
1305
|
-
};
|
|
1306
|
-
|
|
1307
|
-
this.toggleRef = React.createRef();
|
|
1308
|
-
|
|
1309
|
-
this.options = [
|
|
1310
|
-
<SelectOption key={0} value="Active" description="This is a description" />,
|
|
1311
|
-
<SelectOption key={1} value="Cancelled" />,
|
|
1312
|
-
<SelectOption key={2} value="Paused" />,
|
|
1313
|
-
<SelectOption key={4} value="Warning" />,
|
|
1314
|
-
<SelectOption key={5} value="Restarted" />
|
|
1315
|
-
];
|
|
1316
|
-
|
|
1317
|
-
this.onToggle = (_event, isOpen) => {
|
|
1318
|
-
this.setState({ isOpen });
|
|
1319
|
-
};
|
|
1320
|
-
|
|
1321
|
-
this.onSelect = (event, selection) => {
|
|
1322
|
-
this.setState({ selected: selection, isOpen: false }), console.log('selected: ', selection);
|
|
1323
|
-
this.toggleRef.current.focus();
|
|
1324
|
-
};
|
|
1325
|
-
|
|
1326
|
-
this.onFilter = (_, textInput) => {
|
|
1327
|
-
if (textInput === '') {
|
|
1328
|
-
return this.options;
|
|
1329
|
-
} else {
|
|
1330
|
-
this.setState(
|
|
1331
|
-
prevState => ({ selected: [...prevState.selected, selection] }),
|
|
1332
|
-
() => console.log('selections: ', this.state.selected)
|
|
1333
|
-
);
|
|
1334
|
-
}
|
|
1335
|
-
};
|
|
1336
|
-
|
|
1337
|
-
this.clearSelection = () => {
|
|
1338
|
-
this.setState({
|
|
1339
|
-
selected: []
|
|
1340
|
-
});
|
|
1341
|
-
};
|
|
1342
|
-
}
|
|
1343
|
-
|
|
1344
|
-
render() {
|
|
1345
|
-
const { isOpen, selected, isDisabled, direction, isToggleIcon } = this.state;
|
|
1346
|
-
const titleId = 'title-id-footer-checkbox';
|
|
1347
|
-
return (
|
|
1348
|
-
<div>
|
|
1349
|
-
<span id={titleId} hidden>
|
|
1350
|
-
Title
|
|
1351
|
-
</span>
|
|
1352
|
-
<Select
|
|
1353
|
-
variant={SelectVariant.single}
|
|
1354
|
-
toggleRef={this.toggleRef}
|
|
1355
|
-
onToggle={this.onToggle}
|
|
1356
|
-
onSelect={this.onSelect}
|
|
1357
|
-
selections={selected}
|
|
1358
|
-
isOpen={isOpen}
|
|
1359
|
-
placeholderText="Filter by status"
|
|
1360
|
-
aria-labelledby={titleId}
|
|
1361
|
-
footer={
|
|
1362
|
-
<Button variant="link" isInline>
|
|
1363
|
-
Action
|
|
1364
|
-
</Button>
|
|
1365
|
-
}
|
|
1366
|
-
>
|
|
1367
|
-
{this.options}
|
|
1368
|
-
</Select>
|
|
1369
|
-
</div>
|
|
1370
|
-
);
|
|
1371
|
-
}
|
|
1372
|
-
}
|
|
1373
|
-
```
|
|
1374
|
-
|
|
1375
|
-
### Checkbox select with view more
|
|
1376
|
-
|
|
1377
|
-
When a "view more" link is used alongside checkbox input, selections that users make prior to clicking "view more" are persisted after the click.
|
|
1378
|
-
|
|
1379
|
-
```js
|
|
1380
|
-
import React from 'react';
|
|
1381
|
-
import { Select, SelectOption, SelectVariant } from '@patternfly/react-core';
|
|
1382
|
-
|
|
1383
|
-
class SelectViewMoreCheckbox extends React.Component {
|
|
1384
|
-
constructor(props) {
|
|
1385
|
-
super(props);
|
|
1386
|
-
|
|
1387
|
-
this.state = {
|
|
1388
|
-
isOpen: false,
|
|
1389
|
-
selected: [],
|
|
1390
|
-
numOptions: 3,
|
|
1391
|
-
isLoading: false
|
|
1392
|
-
};
|
|
1393
|
-
|
|
1394
|
-
this.options = [
|
|
1395
|
-
<SelectOption key={0} value="Active" description="This is a description" />,
|
|
1396
|
-
<SelectOption key={1} value="Cancelled" />,
|
|
1397
|
-
<SelectOption key={2} value="Paused" />,
|
|
1398
|
-
<SelectOption key={4} value="Warning" />,
|
|
1399
|
-
<SelectOption key={5} value="Restarted" />,
|
|
1400
|
-
<SelectOption key={6} value="Down" />,
|
|
1401
|
-
<SelectOption key={7} value="Disabled" />,
|
|
1402
|
-
<SelectOption key={8} value="Needs maintenance " />,
|
|
1403
|
-
<SelectOption key={9} value="Degraded " />
|
|
1404
|
-
];
|
|
1405
|
-
|
|
1406
|
-
this.onToggle = (_event, isOpen) => {
|
|
1407
|
-
this.setState({
|
|
1408
|
-
isOpen
|
|
1409
|
-
});
|
|
1410
|
-
};
|
|
1411
|
-
|
|
1412
|
-
this.onSelect = (event, selection) => {
|
|
1413
|
-
const { selected } = this.state;
|
|
1414
|
-
if (selected.includes(selection)) {
|
|
1415
|
-
this.setState(
|
|
1416
|
-
prevState => ({ selected: prevState.selected.filter(item => item !== selection) }),
|
|
1417
|
-
() => console.log('selections: ', this.state.selected)
|
|
1418
|
-
);
|
|
1419
|
-
} else {
|
|
1420
|
-
this.setState(
|
|
1421
|
-
prevState => ({ selected: [...prevState.selected, selection] }),
|
|
1422
|
-
() => console.log('selections: ', this.state.selected)
|
|
1423
|
-
);
|
|
1424
|
-
}
|
|
1425
|
-
};
|
|
1426
|
-
|
|
1427
|
-
this.clearSelection = () => {
|
|
1428
|
-
this.setState({
|
|
1429
|
-
selected: []
|
|
1430
|
-
});
|
|
1431
|
-
};
|
|
1432
|
-
|
|
1433
|
-
this.simulateNetworkCall = callback => {
|
|
1434
|
-
setTimeout(callback, 2000);
|
|
1435
|
-
};
|
|
1436
|
-
|
|
1437
|
-
this.onViewMoreClick = () => {
|
|
1438
|
-
// Set select loadingVariant to spinner then simulate network call before loading more options
|
|
1439
|
-
this.setState({ isLoading: true });
|
|
1440
|
-
this.simulateNetworkCall(() => {
|
|
1441
|
-
const newLength =
|
|
1442
|
-
this.state.numOptions + 3 <= this.options.length ? this.state.numOptions + 3 : this.options.length;
|
|
1443
|
-
this.setState({ numOptions: newLength, isLoading: false });
|
|
1444
|
-
});
|
|
1445
|
-
};
|
|
1446
|
-
}
|
|
1447
|
-
|
|
1448
|
-
render() {
|
|
1449
|
-
const { isOpen, selected, numOptions, isLoading } = this.state;
|
|
1450
|
-
const titleId = 'view-more-checkbox-select-id';
|
|
1451
|
-
return (
|
|
1452
|
-
<div>
|
|
1453
|
-
<span id={titleId} hidden>
|
|
1454
|
-
Checkbox View more check
|
|
1455
|
-
</span>
|
|
1456
|
-
<Select
|
|
1457
|
-
variant={SelectVariant.checkbox}
|
|
1458
|
-
aria-label="Select input"
|
|
1459
|
-
onToggle={this.onToggle}
|
|
1460
|
-
onSelect={this.onSelect}
|
|
1461
|
-
selections={selected}
|
|
1462
|
-
isOpen={isOpen}
|
|
1463
|
-
placeholderText="Filter by status"
|
|
1464
|
-
aria-labelledby={titleId}
|
|
1465
|
-
{...(!isLoading &&
|
|
1466
|
-
numOptions < this.options.length && {
|
|
1467
|
-
loadingVariant: { text: 'View more', onClick: this.onViewMoreClick }
|
|
1468
|
-
})}
|
|
1469
|
-
{...(isLoading && { loadingVariant: 'spinner' })}
|
|
1470
|
-
>
|
|
1471
|
-
{this.options.slice(0, numOptions)}
|
|
1472
|
-
</Select>
|
|
1473
|
-
</div>
|
|
1474
|
-
);
|
|
1475
|
-
}
|
|
1476
|
-
}
|
|
1477
|
-
```
|
|
1478
|
-
|
|
1479
|
-
### Filtering with placeholder text
|
|
1480
|
-
|
|
1481
|
-
To preload a filter search bar with placeholder text, use the `inlineFilterPlaceholderText` property. The following example preloads the search bar with "Filter by status".
|
|
1482
|
-
|
|
1483
|
-
```js
|
|
1484
|
-
import React from 'react';
|
|
1485
|
-
import { Select, SelectOption, SelectGroup, SelectVariant } from '@patternfly/react-core';
|
|
1486
|
-
|
|
1487
|
-
class FilteringCheckboxSelectInputWithPlaceholder extends React.Component {
|
|
1488
|
-
constructor(props) {
|
|
1489
|
-
super(props);
|
|
1490
|
-
|
|
1491
|
-
this.state = {
|
|
1492
|
-
isOpen: false,
|
|
1493
|
-
selected: []
|
|
1494
|
-
};
|
|
1495
|
-
|
|
1496
|
-
this.options = [
|
|
1497
|
-
<SelectGroup label="Status" key="group1">
|
|
1498
|
-
<SelectOption key={0} value="Running" />
|
|
1499
|
-
<SelectOption key={1} value="Stopped" />
|
|
1500
|
-
<SelectOption key={2} value="Down" />
|
|
1501
|
-
<SelectOption key={3} value="Degraded" />
|
|
1502
|
-
<SelectOption key={4} value="Needs maintenance" />
|
|
1503
|
-
</SelectGroup>,
|
|
1504
|
-
<SelectGroup label="Vendor names" key="group2">
|
|
1505
|
-
<SelectOption key={5} value="Dell" />
|
|
1506
|
-
<SelectOption key={6} value="Samsung" isDisabled />
|
|
1507
|
-
<SelectOption key={7} value="Hewlett-Packard" />
|
|
1508
|
-
</SelectGroup>
|
|
1509
|
-
];
|
|
1510
|
-
|
|
1511
|
-
this.onToggle = (_event, isOpen) => {
|
|
1512
|
-
this.setState({
|
|
1513
|
-
isOpen
|
|
1514
|
-
});
|
|
1515
|
-
};
|
|
1516
|
-
|
|
1517
|
-
this.onSelect = (event, selection) => {
|
|
1518
|
-
const { selected } = this.state;
|
|
1519
|
-
if (selected.includes(selection)) {
|
|
1520
|
-
this.setState(
|
|
1521
|
-
prevState => ({ selected: prevState.selected.filter(item => item !== selection) }),
|
|
1522
|
-
() => console.log('selections: ', this.state.selected)
|
|
1523
|
-
);
|
|
1524
|
-
} else {
|
|
1525
|
-
this.setState(
|
|
1526
|
-
prevState => ({ selected: [...prevState.selected, selection] }),
|
|
1527
|
-
() => console.log('selections: ', this.state.selected)
|
|
1528
|
-
);
|
|
1529
|
-
}
|
|
1530
|
-
};
|
|
1531
|
-
|
|
1532
|
-
this.onFilter = (_, textInput) => {
|
|
1533
|
-
if (textInput === '') {
|
|
1534
|
-
return this.options;
|
|
1535
|
-
} else {
|
|
1536
|
-
let filteredGroups = this.options
|
|
1537
|
-
.map(group => {
|
|
1538
|
-
let filteredGroup = React.cloneElement(group, {
|
|
1539
|
-
children: group.props.children.filter(item => {
|
|
1540
|
-
return item.props.value.toLowerCase().includes(textInput.toLowerCase());
|
|
1541
|
-
})
|
|
1542
|
-
});
|
|
1543
|
-
if (filteredGroup.props.children.length > 0) return filteredGroup;
|
|
1544
|
-
})
|
|
1545
|
-
.filter(newGroup => newGroup);
|
|
1546
|
-
return filteredGroups;
|
|
1547
|
-
}
|
|
1548
|
-
};
|
|
1549
|
-
|
|
1550
|
-
this.clearSelection = () => {
|
|
1551
|
-
this.setState({
|
|
1552
|
-
selected: []
|
|
1553
|
-
});
|
|
1554
|
-
};
|
|
1555
|
-
}
|
|
1556
|
-
|
|
1557
|
-
render() {
|
|
1558
|
-
const { isOpen, selected, filteredOptions } = this.state;
|
|
1559
|
-
const titleId = 'checkbox-filtering-with-placeholder-select-id';
|
|
1560
|
-
return (
|
|
1561
|
-
<div>
|
|
1562
|
-
<span id={titleId} hidden>
|
|
1563
|
-
Checkbox Title
|
|
1564
|
-
</span>
|
|
1565
|
-
<Select
|
|
1566
|
-
variant={SelectVariant.checkbox}
|
|
1567
|
-
onToggle={this.onToggle}
|
|
1568
|
-
onSelect={this.onSelect}
|
|
1569
|
-
selections={selected}
|
|
1570
|
-
isOpen={isOpen}
|
|
1571
|
-
placeholderText="Filter by status"
|
|
1572
|
-
aria-labelledby={titleId}
|
|
1573
|
-
onFilter={this.onFilter}
|
|
1574
|
-
onClear={this.clearSelection}
|
|
1575
|
-
isGrouped
|
|
1576
|
-
hasInlineFilter
|
|
1577
|
-
inlineFilterPlaceholderText="Filter by status"
|
|
1578
|
-
>
|
|
1579
|
-
{this.options}
|
|
1580
|
-
</Select>
|
|
1581
|
-
</div>
|
|
1582
|
-
);
|
|
1583
|
-
}
|
|
1584
|
-
}
|
|
1585
|
-
```
|
|
1586
|
-
|
|
1587
|
-
### Inline filtering
|
|
1588
|
-
|
|
1589
|
-
To allow users to filter select lists using text input, use the `hasInlineFilter` property. Filtering behavior can be further customized with other properties, as shown in the example below. Select each checkbox to visualize the following behavior:
|
|
1590
|
-
|
|
1591
|
-
- To persist filter results on blur, use the `isInputValuePersisted` property.
|
|
1592
|
-
- To persist a filter that a user has searched, use the `isInputFilterPersisted` property.
|
|
1593
|
-
- To allow users to add new items to a select list, use the `isCreatable` property. When this property is applied and a user searches for an option that doesn't exist, they will be prompted to "create" the item.
|
|
1594
|
-
|
|
1595
|
-
```js
|
|
1596
|
-
import React from 'react';
|
|
1597
|
-
import { Select, SelectOption, SelectGroup, SelectVariant, Checkbox } from '@patternfly/react-core';
|
|
1598
|
-
|
|
1599
|
-
class FilteringSingleSelectInput extends React.Component {
|
|
1600
|
-
constructor(props) {
|
|
1601
|
-
super(props);
|
|
1602
|
-
|
|
1603
|
-
this.state = {
|
|
1604
|
-
isOpen: false,
|
|
1605
|
-
selected: '',
|
|
1606
|
-
isCreatable: false,
|
|
1607
|
-
isInputValuePersisted: false,
|
|
1608
|
-
isInputFilterPersisted: false
|
|
1609
|
-
};
|
|
1610
|
-
|
|
1611
|
-
this.options = [
|
|
1612
|
-
<SelectGroup label="Status" key="group1">
|
|
1613
|
-
<SelectOption key={0} value="Running" />
|
|
1614
|
-
<SelectOption key={1} value="Stopped" />
|
|
1615
|
-
<SelectOption key={2} value="Down" />
|
|
1616
|
-
<SelectOption key={3} value="Degraded" />
|
|
1617
|
-
<SelectOption key={4} value="Needs maintenance" />
|
|
1618
|
-
</SelectGroup>,
|
|
1619
|
-
<SelectGroup label="Vendor names" key="group2">
|
|
1620
|
-
<SelectOption key={5} value="Dell" />
|
|
1621
|
-
<SelectOption key={6} value="Samsung" isDisabled />
|
|
1622
|
-
<SelectOption key={7} value="Hewlett-Packard" />
|
|
1623
|
-
</SelectGroup>
|
|
1624
|
-
];
|
|
1625
|
-
|
|
1626
|
-
this.onToggle = (_event, isOpen) => {
|
|
1627
|
-
this.setState({
|
|
1628
|
-
isOpen
|
|
1629
|
-
});
|
|
1630
|
-
};
|
|
1631
|
-
|
|
1632
|
-
this.onSelect = (event, selection) => {
|
|
1633
|
-
this.setState({ selected: selection, isOpen: false }), console.log('selected: ', selection);
|
|
1634
|
-
};
|
|
1635
|
-
|
|
1636
|
-
this.onFilter = (_, textInput) => {
|
|
1637
|
-
if (textInput === '') {
|
|
1638
|
-
return this.options;
|
|
1639
|
-
} else {
|
|
1640
|
-
let filteredGroups = this.options
|
|
1641
|
-
.map(group => {
|
|
1642
|
-
let filteredGroup = React.cloneElement(group, {
|
|
1643
|
-
children: group.props.children.filter(item => {
|
|
1644
|
-
return item.props.value.toLowerCase().includes(textInput.toLowerCase());
|
|
1645
|
-
})
|
|
1646
|
-
});
|
|
1647
|
-
if (filteredGroup.props.children.length > 0) return filteredGroup;
|
|
1648
|
-
})
|
|
1649
|
-
.filter(Boolean);
|
|
1650
|
-
return filteredGroups;
|
|
1651
|
-
}
|
|
1652
|
-
};
|
|
1653
|
-
|
|
1654
|
-
this.toggleCreatable = (_, checked) => {
|
|
1655
|
-
this.setState({
|
|
1656
|
-
isCreatable: checked
|
|
1657
|
-
});
|
|
1658
|
-
};
|
|
1659
|
-
|
|
1660
|
-
this.toggleInputValuePersisted = (_, checked) => {
|
|
1661
|
-
this.setState({
|
|
1662
|
-
isInputValuePersisted: checked
|
|
1663
|
-
});
|
|
1664
|
-
};
|
|
1665
|
-
|
|
1666
|
-
this.toggleInputFilterPersisted = (_, checked) => {
|
|
1667
|
-
this.setState({
|
|
1668
|
-
isInputFilterPersisted: checked
|
|
1669
|
-
});
|
|
1670
|
-
};
|
|
1671
|
-
}
|
|
1672
|
-
|
|
1673
|
-
render() {
|
|
1674
|
-
const {
|
|
1675
|
-
isOpen,
|
|
1676
|
-
selected,
|
|
1677
|
-
filteredOptions,
|
|
1678
|
-
isInputValuePersisted,
|
|
1679
|
-
isInputFilterPersisted,
|
|
1680
|
-
isCreatable
|
|
1681
|
-
} = this.state;
|
|
1682
|
-
const titleId = 'single-filtering-select-id';
|
|
1683
|
-
return (
|
|
1684
|
-
<div>
|
|
1685
|
-
<span id={titleId} hidden>
|
|
1686
|
-
Single select with filter
|
|
1687
|
-
</span>
|
|
1688
|
-
<Select
|
|
1689
|
-
variant={SelectVariant.single}
|
|
1690
|
-
onToggle={this.onToggle}
|
|
1691
|
-
onSelect={this.onSelect}
|
|
1692
|
-
selections={selected}
|
|
1693
|
-
isOpen={isOpen}
|
|
1694
|
-
placeholderText="Filter by status"
|
|
1695
|
-
aria-labelledby={titleId}
|
|
1696
|
-
onFilter={this.onFilter}
|
|
1697
|
-
isGrouped
|
|
1698
|
-
hasInlineFilter
|
|
1699
|
-
isCreatable={isCreatable}
|
|
1700
|
-
isInputValuePersisted={isInputValuePersisted}
|
|
1701
|
-
isInputFilterPersisted={isInputFilterPersisted}
|
|
1702
|
-
>
|
|
1703
|
-
{this.options}
|
|
1704
|
-
</Select>
|
|
1705
|
-
<Checkbox
|
|
1706
|
-
label="isInputValuePersisted"
|
|
1707
|
-
isChecked={isInputValuePersisted}
|
|
1708
|
-
onChange={this.toggleInputValuePersisted}
|
|
1709
|
-
aria-label="toggle input value persisted"
|
|
1710
|
-
id="toggle-inline-filter-input-value-persisted"
|
|
1711
|
-
name="toggle-inline-filter-input-value-persisted"
|
|
1712
|
-
/>
|
|
1713
|
-
<Checkbox
|
|
1714
|
-
label="isInputFilterPersisted"
|
|
1715
|
-
isChecked={isInputFilterPersisted}
|
|
1716
|
-
onChange={this.toggleInputFilterPersisted}
|
|
1717
|
-
aria-label="toggle input filter persisted"
|
|
1718
|
-
id="toggle-inline-filter-input-filter-persisted"
|
|
1719
|
-
name="toggle-inline-filter-input-filter-persisted"
|
|
1720
|
-
/>
|
|
1721
|
-
<Checkbox
|
|
1722
|
-
label="isCreatable"
|
|
1723
|
-
isChecked={this.state.isCreatable}
|
|
1724
|
-
onChange={this.toggleCreatable}
|
|
1725
|
-
aria-label="toggle creatable checkbox"
|
|
1726
|
-
id="toggle-inline-filter-creatable-typeahead"
|
|
1727
|
-
name="toggle-inline-filter-creatable-typeahead"
|
|
1728
|
-
/>
|
|
1729
|
-
</div>
|
|
1730
|
-
);
|
|
1731
|
-
}
|
|
1732
|
-
}
|
|
26
|
+
```ts file="./SelectCheckbox.tsx"
|
|
1733
27
|
```
|
|
1734
28
|
|
|
1735
29
|
### Typeahead
|
|
1736
30
|
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
To make a typeahead, pass `variant=typeahead` into the `<Select>` component. To specify a label for the input field, use the `typeAheadAriaLabel` property.
|
|
1740
|
-
|
|
1741
|
-
A few additional customization options are shown in the example below. Select each checkbox to visualize the following behavior:
|
|
1742
|
-
|
|
1743
|
-
- To place a created item at the top of a typeahead list use the `isCreateOptionOnTop` property.
|
|
1744
|
-
- To trigger a callback for newly created items, use the `onCreateOption` property.
|
|
1745
|
-
- To reset the typeahead value after a user makes a selection, use the `shouldResetOnSelect` property.
|
|
1746
|
-
|
|
1747
|
-
```js
|
|
1748
|
-
import React from 'react';
|
|
1749
|
-
import { Checkbox, Select, SelectOption, SelectVariant } from '@patternfly/react-core';
|
|
1750
|
-
|
|
1751
|
-
class TypeaheadSelectInput extends React.Component {
|
|
1752
|
-
constructor(props) {
|
|
1753
|
-
super(props);
|
|
1754
|
-
this.defaultOptions = [
|
|
1755
|
-
{ value: 'Alabama' },
|
|
1756
|
-
{ value: 'Florida', description: 'This is a description' },
|
|
1757
|
-
{ value: 'New Jersey' },
|
|
1758
|
-
{ value: 'New Mexico' },
|
|
1759
|
-
{ value: 'New York' },
|
|
1760
|
-
{ value: 'North Carolina' }
|
|
1761
|
-
];
|
|
1762
|
-
|
|
1763
|
-
this.state = {
|
|
1764
|
-
options: this.defaultOptions,
|
|
1765
|
-
isOpen: false,
|
|
1766
|
-
selected: null,
|
|
1767
|
-
isDisabled: false,
|
|
1768
|
-
isCreatable: false,
|
|
1769
|
-
isCreateOptionOnTop: false,
|
|
1770
|
-
isInputValuePersisted: false,
|
|
1771
|
-
isInputFilterPersisted: false,
|
|
1772
|
-
hasOnCreateOption: false,
|
|
1773
|
-
resetOnSelect: true
|
|
1774
|
-
};
|
|
1775
|
-
|
|
1776
|
-
this.onToggle = (_event, isOpen) => {
|
|
1777
|
-
this.setState({
|
|
1778
|
-
isOpen
|
|
1779
|
-
});
|
|
1780
|
-
};
|
|
1781
|
-
|
|
1782
|
-
this.onSelect = (event, selection, isPlaceholder) => {
|
|
1783
|
-
if (isPlaceholder) this.clearSelection();
|
|
1784
|
-
else {
|
|
1785
|
-
this.setState({
|
|
1786
|
-
selected: selection,
|
|
1787
|
-
isOpen: this.state.resetOnSelect ? false : this.state.isOpen
|
|
1788
|
-
});
|
|
1789
|
-
console.log('selected:', selection);
|
|
1790
|
-
}
|
|
1791
|
-
};
|
|
1792
|
-
|
|
1793
|
-
this.onCreateOption = newValue => {
|
|
1794
|
-
this.setState({
|
|
1795
|
-
options: [...this.state.options, { value: newValue }]
|
|
1796
|
-
});
|
|
1797
|
-
};
|
|
1798
|
-
|
|
1799
|
-
this.clearSelection = () => {
|
|
1800
|
-
this.setState({
|
|
1801
|
-
selected: null,
|
|
1802
|
-
isOpen: false,
|
|
1803
|
-
options: this.defaultOptions
|
|
1804
|
-
});
|
|
1805
|
-
};
|
|
1806
|
-
|
|
1807
|
-
this.toggleDisabled = checked => {
|
|
1808
|
-
this.setState({
|
|
1809
|
-
isDisabled: checked
|
|
1810
|
-
});
|
|
1811
|
-
};
|
|
1812
|
-
|
|
1813
|
-
this.toggleCreatable = checked => {
|
|
1814
|
-
this.setState({
|
|
1815
|
-
isCreatable: checked
|
|
1816
|
-
});
|
|
1817
|
-
};
|
|
1818
|
-
|
|
1819
|
-
this.toggleCreateOptionOnTop = checked => {
|
|
1820
|
-
this.setState({
|
|
1821
|
-
isCreateOptionOnTop: checked
|
|
1822
|
-
});
|
|
1823
|
-
};
|
|
1824
|
-
|
|
1825
|
-
this.toggleCreateNew = checked => {
|
|
1826
|
-
this.setState({
|
|
1827
|
-
hasOnCreateOption: checked
|
|
1828
|
-
});
|
|
1829
|
-
};
|
|
1830
|
-
|
|
1831
|
-
this.toggleInputValuePersisted = checked => {
|
|
1832
|
-
this.setState({
|
|
1833
|
-
isInputValuePersisted: checked
|
|
1834
|
-
});
|
|
1835
|
-
};
|
|
1836
|
-
|
|
1837
|
-
this.toggleInputFilterPersisted = checked => {
|
|
1838
|
-
this.setState({
|
|
1839
|
-
isInputFilterPersisted: checked
|
|
1840
|
-
});
|
|
1841
|
-
};
|
|
1842
|
-
|
|
1843
|
-
this.toggleResetOnSelect = checked => {
|
|
1844
|
-
this.setState({
|
|
1845
|
-
resetOnSelect: checked
|
|
1846
|
-
});
|
|
1847
|
-
};
|
|
1848
|
-
}
|
|
1849
|
-
|
|
1850
|
-
render() {
|
|
1851
|
-
const {
|
|
1852
|
-
isOpen,
|
|
1853
|
-
selected,
|
|
1854
|
-
isDisabled,
|
|
1855
|
-
isCreatable,
|
|
1856
|
-
isCreateOptionOnTop,
|
|
1857
|
-
hasOnCreateOption,
|
|
1858
|
-
isInputValuePersisted,
|
|
1859
|
-
isInputFilterPersisted,
|
|
1860
|
-
resetOnSelect,
|
|
1861
|
-
options
|
|
1862
|
-
} = this.state;
|
|
1863
|
-
const titleId = 'typeahead-select-id-1';
|
|
1864
|
-
return (
|
|
1865
|
-
<div>
|
|
1866
|
-
<span id={titleId} hidden>
|
|
1867
|
-
Select a state
|
|
1868
|
-
</span>
|
|
1869
|
-
<Select
|
|
1870
|
-
variant={SelectVariant.typeahead}
|
|
1871
|
-
typeAheadAriaLabel="Select a state"
|
|
1872
|
-
onToggle={this.onToggle}
|
|
1873
|
-
onSelect={this.onSelect}
|
|
1874
|
-
onClear={this.clearSelection}
|
|
1875
|
-
selections={selected}
|
|
1876
|
-
isOpen={isOpen}
|
|
1877
|
-
aria-labelledby={titleId}
|
|
1878
|
-
isInputValuePersisted={isInputValuePersisted}
|
|
1879
|
-
isInputFilterPersisted={isInputFilterPersisted}
|
|
1880
|
-
placeholderText="Select a state"
|
|
1881
|
-
isDisabled={isDisabled}
|
|
1882
|
-
isCreatable={isCreatable}
|
|
1883
|
-
isCreateOptionOnTop={isCreateOptionOnTop}
|
|
1884
|
-
onCreateOption={(hasOnCreateOption && this.onCreateOption) || undefined}
|
|
1885
|
-
shouldResetOnSelect={resetOnSelect}
|
|
1886
|
-
>
|
|
1887
|
-
{options.map((option, index) => (
|
|
1888
|
-
<SelectOption
|
|
1889
|
-
isDisabled={option.disabled}
|
|
1890
|
-
key={index}
|
|
1891
|
-
value={option.value}
|
|
1892
|
-
{...(option.description && { description: option.description })}
|
|
1893
|
-
/>
|
|
1894
|
-
))}
|
|
1895
|
-
</Select>
|
|
1896
|
-
<Checkbox
|
|
1897
|
-
label="isDisabled"
|
|
1898
|
-
isChecked={this.state.isDisabled}
|
|
1899
|
-
onChange={(_event, checked) => this.toggleDisabled(checked)}
|
|
1900
|
-
aria-label="toggle disabled checkbox"
|
|
1901
|
-
id="toggle-disabled-typeahead"
|
|
1902
|
-
name="toggle-disabled-typeahead"
|
|
1903
|
-
/>
|
|
1904
|
-
<Checkbox
|
|
1905
|
-
label="isCreatable"
|
|
1906
|
-
isChecked={this.state.isCreatable}
|
|
1907
|
-
onChange={(_event, checked) => this.toggleCreatable(checked)}
|
|
1908
|
-
aria-label="toggle creatable checkbox"
|
|
1909
|
-
id="toggle-creatable-typeahead"
|
|
1910
|
-
name="toggle-creatable-typeahead"
|
|
1911
|
-
/>
|
|
1912
|
-
<Checkbox
|
|
1913
|
-
label="isCreateOptionOnTop"
|
|
1914
|
-
isChecked={this.state.isCreateOptionOnTop}
|
|
1915
|
-
onChange={(_event, checked) => this.toggleCreateOptionOnTop(checked)}
|
|
1916
|
-
aria-label="toggle createOptionOnTop checkbox"
|
|
1917
|
-
id="toggle-create-option-on-top-typeahead"
|
|
1918
|
-
name="toggle-create-option-on-top-typeahead"
|
|
1919
|
-
/>
|
|
1920
|
-
<Checkbox
|
|
1921
|
-
label="onCreateOption"
|
|
1922
|
-
isChecked={this.state.hasOnCreateOption}
|
|
1923
|
-
onChange={(_event, checked) => this.toggleCreateNew(checked)}
|
|
1924
|
-
aria-label="toggle new checkbox"
|
|
1925
|
-
id="toggle-new-typeahead"
|
|
1926
|
-
name="toggle-new-typeahead"
|
|
1927
|
-
/>
|
|
1928
|
-
<Checkbox
|
|
1929
|
-
label="isInputValuePersisted"
|
|
1930
|
-
isChecked={isInputValuePersisted}
|
|
1931
|
-
onChange={(_event, checked) => this.toggleInputValuePersisted(checked)}
|
|
1932
|
-
aria-label="toggle input value persisted"
|
|
1933
|
-
id="toggle-input-value-persisted"
|
|
1934
|
-
name="toggle-input-value-persisted"
|
|
1935
|
-
/>
|
|
1936
|
-
<Checkbox
|
|
1937
|
-
label="isInputFilterPersisted"
|
|
1938
|
-
isChecked={isInputFilterPersisted}
|
|
1939
|
-
onChange={(_event, checked) => this.toggleInputFilterPersisted(checked)}
|
|
1940
|
-
aria-label="toggle input filter persisted"
|
|
1941
|
-
id="toggle-input-filter-persisted"
|
|
1942
|
-
name="toggle-input-filter-persisted"
|
|
1943
|
-
/>
|
|
1944
|
-
<Checkbox
|
|
1945
|
-
label="shouldResetOnSelect"
|
|
1946
|
-
isChecked={this.state.resetOnSelect}
|
|
1947
|
-
onChange={(_event, checked) => this.toggleResetOnSelect(checked)}
|
|
1948
|
-
aria-label="toggle reset checkbox"
|
|
1949
|
-
id="toggle-reset-typeahead"
|
|
1950
|
-
name="toggle-reset-typeahead"
|
|
1951
|
-
/>
|
|
1952
|
-
</div>
|
|
1953
|
-
);
|
|
1954
|
-
}
|
|
1955
|
-
}
|
|
1956
|
-
```
|
|
1957
|
-
|
|
1958
|
-
### Grouped typeahead
|
|
1959
|
-
|
|
1960
|
-
Typeahead matches items with user input across groups.
|
|
1961
|
-
|
|
1962
|
-
```js
|
|
1963
|
-
import React from 'react';
|
|
1964
|
-
import { Checkbox, Select, SelectGroup, SelectOption, SelectVariant, Divider } from '@patternfly/react-core';
|
|
1965
|
-
|
|
1966
|
-
class GroupedTypeaheadSelectInput extends React.Component {
|
|
1967
|
-
constructor(props) {
|
|
1968
|
-
super(props);
|
|
1969
|
-
|
|
1970
|
-
this.state = {
|
|
1971
|
-
options: [
|
|
1972
|
-
<SelectGroup label="Status" key="group1">
|
|
1973
|
-
<SelectOption key={0} value="Running" />
|
|
1974
|
-
<SelectOption key={1} value="Stopped" />
|
|
1975
|
-
<SelectOption key={2} value="Down" />
|
|
1976
|
-
<SelectOption key={3} value="Degraded" />
|
|
1977
|
-
<SelectOption key={4} value="Needs maintenance" />
|
|
1978
|
-
</SelectGroup>,
|
|
1979
|
-
<Divider key="divider" />,
|
|
1980
|
-
<SelectGroup label="Vendor names" key="group2">
|
|
1981
|
-
<SelectOption key={5} value="Dell" />
|
|
1982
|
-
<SelectOption key={6} value="Samsung" isDisabled />
|
|
1983
|
-
<SelectOption key={7} value="Hewlett-Packard" />
|
|
1984
|
-
</SelectGroup>
|
|
1985
|
-
],
|
|
1986
|
-
newOptions: [],
|
|
1987
|
-
isOpen: false,
|
|
1988
|
-
selected: null,
|
|
1989
|
-
isCreatable: false,
|
|
1990
|
-
hasOnCreateOption: false
|
|
1991
|
-
};
|
|
1992
|
-
|
|
1993
|
-
this.onToggle = (_event, isOpen) => {
|
|
1994
|
-
this.setState({
|
|
1995
|
-
isOpen
|
|
1996
|
-
});
|
|
1997
|
-
};
|
|
1998
|
-
|
|
1999
|
-
this.onSelect = (event, selection, isPlaceholder) => {
|
|
2000
|
-
if (isPlaceholder) this.clearSelection();
|
|
2001
|
-
else {
|
|
2002
|
-
this.setState({
|
|
2003
|
-
selected: selection,
|
|
2004
|
-
isOpen: false
|
|
2005
|
-
});
|
|
2006
|
-
console.log('selected:', selection);
|
|
2007
|
-
}
|
|
2008
|
-
};
|
|
2009
|
-
|
|
2010
|
-
this.onCreateOption = newValue => {
|
|
2011
|
-
this.setState({
|
|
2012
|
-
newOptions: [...this.state.newOptions, <SelectOption key={newValue} value={newValue} />]
|
|
2013
|
-
});
|
|
2014
|
-
};
|
|
2015
|
-
|
|
2016
|
-
this.clearSelection = () => {
|
|
2017
|
-
this.setState({
|
|
2018
|
-
selected: null,
|
|
2019
|
-
isOpen: false
|
|
2020
|
-
});
|
|
2021
|
-
};
|
|
2022
|
-
|
|
2023
|
-
this.toggleCreatable = checked => {
|
|
2024
|
-
this.setState({
|
|
2025
|
-
isCreatable: checked
|
|
2026
|
-
});
|
|
2027
|
-
};
|
|
2028
|
-
|
|
2029
|
-
this.toggleCreateNew = checked => {
|
|
2030
|
-
this.setState({
|
|
2031
|
-
hasOnCreateOption: checked
|
|
2032
|
-
});
|
|
2033
|
-
};
|
|
2034
|
-
}
|
|
2035
|
-
|
|
2036
|
-
render() {
|
|
2037
|
-
const { isOpen, selected, isDisabled, isCreatable, hasOnCreateOption, options, newOptions } = this.state;
|
|
2038
|
-
const titleId = 'grouped-typeahead-select-id';
|
|
2039
|
-
const allOptions =
|
|
2040
|
-
newOptions.length > 0
|
|
2041
|
-
? options.concat(
|
|
2042
|
-
<SelectGroup label="Created" key="create-group">
|
|
2043
|
-
{newOptions}
|
|
2044
|
-
</SelectGroup>
|
|
2045
|
-
)
|
|
2046
|
-
: options;
|
|
2047
|
-
return (
|
|
2048
|
-
<div>
|
|
2049
|
-
<span id={titleId} hidden>
|
|
2050
|
-
Select a state
|
|
2051
|
-
</span>
|
|
2052
|
-
<Select
|
|
2053
|
-
variant={SelectVariant.typeahead}
|
|
2054
|
-
typeAheadAriaLabel="Select a state"
|
|
2055
|
-
onToggle={this.onToggle}
|
|
2056
|
-
onSelect={this.onSelect}
|
|
2057
|
-
onClear={this.clearSelection}
|
|
2058
|
-
selections={selected}
|
|
2059
|
-
isOpen={isOpen}
|
|
2060
|
-
aria-labelledby={titleId}
|
|
2061
|
-
placeholderText="Select a state"
|
|
2062
|
-
isGrouped
|
|
2063
|
-
isCreatable={isCreatable}
|
|
2064
|
-
onCreateOption={(hasOnCreateOption && this.onCreateOption) || undefined}
|
|
2065
|
-
>
|
|
2066
|
-
{allOptions}
|
|
2067
|
-
</Select>
|
|
2068
|
-
<Checkbox
|
|
2069
|
-
label="isCreatable"
|
|
2070
|
-
isChecked={this.state.isCreatable}
|
|
2071
|
-
onChange={(_event, checked) => this.toggleCreatable(checked)}
|
|
2072
|
-
aria-label="toggle creatable checkbox"
|
|
2073
|
-
id="toggle-creatable-grouped-typeahead"
|
|
2074
|
-
name="toggle-creatable-grouped-typeahead"
|
|
2075
|
-
/>
|
|
2076
|
-
<Checkbox
|
|
2077
|
-
label="onCreateOption"
|
|
2078
|
-
isChecked={this.state.hasOnCreateOption}
|
|
2079
|
-
onChange={(_event, checked) => this.toggleCreateNew(checked)}
|
|
2080
|
-
aria-label="toggle new checkbox"
|
|
2081
|
-
id="toggle-new-grouped-typeahead"
|
|
2082
|
-
name="toggle-new-grouped-typeahead"
|
|
2083
|
-
/>
|
|
2084
|
-
</div>
|
|
2085
|
-
);
|
|
2086
|
-
}
|
|
2087
|
-
}
|
|
2088
|
-
```
|
|
2089
|
-
|
|
2090
|
-
### Typeahead with custom filtering
|
|
2091
|
-
|
|
2092
|
-
You can add custom filtering to a select list to better fit needs that aren't covered by inline filtering. If you use custom filtering, use the `onFilter` property to trigger a callback with your custom filter implementation.
|
|
2093
|
-
|
|
2094
|
-
```js
|
|
2095
|
-
import React from 'react';
|
|
2096
|
-
import { Select, SelectOption, SelectVariant } from '@patternfly/react-core';
|
|
2097
|
-
|
|
2098
|
-
class TypeaheadSelectInput extends React.Component {
|
|
2099
|
-
constructor(props) {
|
|
2100
|
-
super(props);
|
|
2101
|
-
this.options = [
|
|
2102
|
-
<SelectOption key={0} value="Alabama" />,
|
|
2103
|
-
<SelectOption key={1} value="Florida" />,
|
|
2104
|
-
<SelectOption key={2} value="New Jersey" />,
|
|
2105
|
-
<SelectOption key={3} value="New Mexico" />,
|
|
2106
|
-
<SelectOption key={4} value="New York" />,
|
|
2107
|
-
<SelectOption key={5} value="North Carolina" />
|
|
2108
|
-
];
|
|
2109
|
-
this.state = {
|
|
2110
|
-
isOpen: false,
|
|
2111
|
-
selected: null
|
|
2112
|
-
};
|
|
2113
|
-
|
|
2114
|
-
this.onToggle = (_event, isOpen) => {
|
|
2115
|
-
this.setState({
|
|
2116
|
-
isOpen
|
|
2117
|
-
});
|
|
2118
|
-
};
|
|
2119
|
-
|
|
2120
|
-
this.onSelect = (event, selection, isPlaceholder) => {
|
|
2121
|
-
if (isPlaceholder) this.clearSelection();
|
|
2122
|
-
else {
|
|
2123
|
-
this.setState({
|
|
2124
|
-
selected: selection,
|
|
2125
|
-
isOpen: false
|
|
2126
|
-
});
|
|
2127
|
-
console.log('selected:', selection);
|
|
2128
|
-
}
|
|
2129
|
-
};
|
|
2130
|
-
|
|
2131
|
-
this.clearSelection = () => {
|
|
2132
|
-
this.setState({
|
|
2133
|
-
selected: null,
|
|
2134
|
-
isOpen: false
|
|
2135
|
-
});
|
|
2136
|
-
};
|
|
2137
|
-
|
|
2138
|
-
this.customFilter = (_, value) => {
|
|
2139
|
-
if (!value) {
|
|
2140
|
-
return this.options;
|
|
2141
|
-
}
|
|
2142
|
-
|
|
2143
|
-
const input = new RegExp(value, 'i');
|
|
2144
|
-
return this.options.filter(child => input.test(child.props.value));
|
|
2145
|
-
};
|
|
2146
|
-
}
|
|
2147
|
-
|
|
2148
|
-
render() {
|
|
2149
|
-
const { isOpen, selected } = this.state;
|
|
2150
|
-
const titleId = 'typeahead-select-id-2';
|
|
2151
|
-
return (
|
|
2152
|
-
<div>
|
|
2153
|
-
<span id={titleId} hidden>
|
|
2154
|
-
Select a state
|
|
2155
|
-
</span>
|
|
2156
|
-
<Select
|
|
2157
|
-
variant={SelectVariant.typeahead}
|
|
2158
|
-
typeAheadAriaLabel="Select a state"
|
|
2159
|
-
onToggle={this.onToggle}
|
|
2160
|
-
onSelect={this.onSelect}
|
|
2161
|
-
onClear={this.clearSelection}
|
|
2162
|
-
onFilter={this.customFilter}
|
|
2163
|
-
selections={selected}
|
|
2164
|
-
isOpen={isOpen}
|
|
2165
|
-
aria-labelledby={titleId}
|
|
2166
|
-
placeholderText="Select a state"
|
|
2167
|
-
>
|
|
2168
|
-
{this.options}
|
|
2169
|
-
</Select>
|
|
2170
|
-
</div>
|
|
2171
|
-
);
|
|
2172
|
-
}
|
|
2173
|
-
}
|
|
31
|
+
```ts file="./SelectTypeahead.tsx"
|
|
2174
32
|
```
|
|
2175
33
|
|
|
2176
|
-
### Multiple
|
|
2177
|
-
|
|
2178
|
-
To create a multiple typeahead select variant, pass `variant={SelectVariant.typeaheadMulti}` into the `<Select>` component. Multiple typeaheads let users select multiple items from a select list. Selected items appear as chips in the select toggle.
|
|
2179
|
-
|
|
2180
|
-
When many items are selected, you can hide overflowing items under a "more" button. The following example hides items after more than 3 are selected. To show hidden items, select the “more” button. Click "show less" to hide extra items again.
|
|
2181
|
-
|
|
2182
|
-
```js
|
|
2183
|
-
import React from 'react';
|
|
2184
|
-
import { Checkbox, Select, SelectOption, SelectVariant } from '@patternfly/react-core';
|
|
2185
|
-
|
|
2186
|
-
class MultiTypeaheadSelectInput extends React.Component {
|
|
2187
|
-
constructor(props) {
|
|
2188
|
-
super(props);
|
|
2189
|
-
|
|
2190
|
-
this.state = {
|
|
2191
|
-
options: [
|
|
2192
|
-
{ value: 'Alabama', disabled: false },
|
|
2193
|
-
{ value: 'Florida', disabled: false },
|
|
2194
|
-
{ value: 'New Jersey', disabled: false },
|
|
2195
|
-
{ value: 'New Mexico', disabled: false, description: 'This is a description' },
|
|
2196
|
-
{ value: 'New York', disabled: false },
|
|
2197
|
-
{ value: 'North Carolina', disabled: false }
|
|
2198
|
-
],
|
|
2199
|
-
isOpen: false,
|
|
2200
|
-
selected: [],
|
|
2201
|
-
isCreatable: false,
|
|
2202
|
-
hasOnCreateOption: false,
|
|
2203
|
-
hasDisabledOption: false,
|
|
2204
|
-
resetOnSelect: true
|
|
2205
|
-
};
|
|
2206
|
-
|
|
2207
|
-
this.onCreateOption = newValue => {
|
|
2208
|
-
this.setState({
|
|
2209
|
-
options: [...this.state.options, { value: newValue }]
|
|
2210
|
-
});
|
|
2211
|
-
};
|
|
2212
|
-
|
|
2213
|
-
this.onToggle = (_event, isOpen) => {
|
|
2214
|
-
this.setState({
|
|
2215
|
-
isOpen
|
|
2216
|
-
});
|
|
2217
|
-
};
|
|
2218
|
-
|
|
2219
|
-
this.onSelect = (event, selection) => {
|
|
2220
|
-
const { selected } = this.state;
|
|
2221
|
-
if (selected.includes(selection)) {
|
|
2222
|
-
this.setState(
|
|
2223
|
-
prevState => ({ selected: prevState.selected.filter(item => item !== selection) }),
|
|
2224
|
-
() => console.log('selections: ', this.state.selected)
|
|
2225
|
-
);
|
|
2226
|
-
} else {
|
|
2227
|
-
this.setState(
|
|
2228
|
-
prevState => ({ selected: [...prevState.selected, selection] }),
|
|
2229
|
-
() => console.log('selections: ', this.state.selected)
|
|
2230
|
-
);
|
|
2231
|
-
}
|
|
2232
|
-
};
|
|
2233
|
-
|
|
2234
|
-
this.clearSelection = () => {
|
|
2235
|
-
this.setState({
|
|
2236
|
-
selected: [],
|
|
2237
|
-
isOpen: false
|
|
2238
|
-
});
|
|
2239
|
-
};
|
|
2240
|
-
|
|
2241
|
-
this.toggleCreatable = checked => {
|
|
2242
|
-
this.setState({
|
|
2243
|
-
isCreatable: checked
|
|
2244
|
-
});
|
|
2245
|
-
};
|
|
2246
|
-
|
|
2247
|
-
this.toggleCreateNew = checked => {
|
|
2248
|
-
this.setState({
|
|
2249
|
-
hasOnCreateOption: checked
|
|
2250
|
-
});
|
|
2251
|
-
};
|
|
2252
|
-
|
|
2253
|
-
this.toggleOptionDisabled = toggleIndex => () => {
|
|
2254
|
-
this.setState(prevState => ({
|
|
2255
|
-
hasDisabledOption: !prevState.hasDisabledOption,
|
|
2256
|
-
options: prevState.options.map((option, index) =>
|
|
2257
|
-
index === toggleIndex ? { ...option, disabled: !option.disabled } : option
|
|
2258
|
-
)
|
|
2259
|
-
}));
|
|
2260
|
-
};
|
|
2261
|
-
|
|
2262
|
-
this.toggleResetOnSelect = checked => {
|
|
2263
|
-
this.setState({
|
|
2264
|
-
resetOnSelect: checked
|
|
2265
|
-
});
|
|
2266
|
-
};
|
|
2267
|
-
}
|
|
2268
|
-
|
|
2269
|
-
render() {
|
|
2270
|
-
const { isOpen, selected, isCreatable, hasOnCreateOption, resetOnSelect, options } = this.state;
|
|
2271
|
-
const titleId = 'multi-typeahead-select-id-1';
|
|
2272
|
-
|
|
2273
|
-
return (
|
|
2274
|
-
<div>
|
|
2275
|
-
<span id={titleId} hidden>
|
|
2276
|
-
Select a state
|
|
2277
|
-
</span>
|
|
2278
|
-
<Select
|
|
2279
|
-
variant={SelectVariant.typeaheadMulti}
|
|
2280
|
-
typeAheadAriaLabel="Select a state"
|
|
2281
|
-
onToggle={this.onToggle}
|
|
2282
|
-
onSelect={this.onSelect}
|
|
2283
|
-
onClear={this.clearSelection}
|
|
2284
|
-
selections={selected}
|
|
2285
|
-
isOpen={isOpen}
|
|
2286
|
-
aria-labelledby={titleId}
|
|
2287
|
-
placeholderText="Select a state"
|
|
2288
|
-
isCreatable={isCreatable}
|
|
2289
|
-
onCreateOption={(hasOnCreateOption && this.onCreateOption) || undefined}
|
|
2290
|
-
shouldResetOnSelect={resetOnSelect}
|
|
2291
|
-
>
|
|
2292
|
-
{options.map((option, index) => (
|
|
2293
|
-
<SelectOption
|
|
2294
|
-
isDisabled={option.disabled}
|
|
2295
|
-
key={index}
|
|
2296
|
-
value={option.value}
|
|
2297
|
-
{...(option.description && { description: option.description })}
|
|
2298
|
-
/>
|
|
2299
|
-
))}
|
|
2300
|
-
</Select>
|
|
2301
|
-
<Checkbox
|
|
2302
|
-
label="isCreatable"
|
|
2303
|
-
isChecked={this.state.isCreatable}
|
|
2304
|
-
onChange={(_event, checked) => this.toggleCreatable(checked)}
|
|
2305
|
-
aria-label="toggle creatable checkbox"
|
|
2306
|
-
id="toggle-creatable-typeahead-multi"
|
|
2307
|
-
name="toggle-creatable-typeahead-multi"
|
|
2308
|
-
/>
|
|
2309
|
-
<Checkbox
|
|
2310
|
-
label="onCreateOption"
|
|
2311
|
-
isChecked={this.state.hasOnCreateOption}
|
|
2312
|
-
onChange={(_event, checked) => this.toggleCreateNew(checked)}
|
|
2313
|
-
aria-label="toggle new checkbox"
|
|
2314
|
-
id="toggle-new-typeahead-multi"
|
|
2315
|
-
name="toggle-new-typeahead-multi"
|
|
2316
|
-
/>
|
|
2317
|
-
<Checkbox
|
|
2318
|
-
label="isDisabled (1st option only)"
|
|
2319
|
-
isChecked={this.state.hasDisabledOption}
|
|
2320
|
-
onChange={this.toggleOptionDisabled(0)}
|
|
2321
|
-
aria-label="toggle disable first option"
|
|
2322
|
-
id="toggle-disable-first-option"
|
|
2323
|
-
name="toggle-disable-first-option"
|
|
2324
|
-
/>
|
|
2325
|
-
<Checkbox
|
|
2326
|
-
label="shouldResetOnSelect"
|
|
2327
|
-
isChecked={this.state.resetOnSelect}
|
|
2328
|
-
onChange={(_event, checked) => this.toggleResetOnSelect(checked)}
|
|
2329
|
-
aria-label="toggle multi reset checkbox"
|
|
2330
|
-
id="toggle-reset-multi-typeahead"
|
|
2331
|
-
name="toggle-reset-multi-typeahead"
|
|
2332
|
-
/>
|
|
2333
|
-
</div>
|
|
2334
|
-
);
|
|
2335
|
-
}
|
|
2336
|
-
}
|
|
2337
|
-
```
|
|
2338
|
-
|
|
2339
|
-
### Multiple typeahead with custom chips
|
|
2340
|
-
|
|
2341
|
-
To customize the appearance of chips, use the `chipGroupProps` property. The `numChips` property allows you to control the number of items shown, while the `expandedText` and `collapsedText` properties allow you to control the labels of the expansion and collapse chips.
|
|
2342
|
-
|
|
2343
|
-
```js
|
|
2344
|
-
import React from 'react';
|
|
2345
|
-
import { Select, SelectOption, SelectVariant } from '@patternfly/react-core';
|
|
2346
|
-
|
|
2347
|
-
class MultiTypeaheadSelectInputWithChipGroupProps extends React.Component {
|
|
2348
|
-
constructor(props) {
|
|
2349
|
-
super(props);
|
|
2350
|
-
|
|
2351
|
-
this.state = {
|
|
2352
|
-
options: [
|
|
2353
|
-
{ value: 'Alabama', disabled: false },
|
|
2354
|
-
{ value: 'Florida', disabled: false },
|
|
2355
|
-
{ value: 'New Jersey', disabled: false },
|
|
2356
|
-
{ value: 'New Mexico', disabled: false, description: 'This is a description' },
|
|
2357
|
-
{ value: 'New York', disabled: false },
|
|
2358
|
-
{ value: 'North Carolina', disabled: false }
|
|
2359
|
-
],
|
|
2360
|
-
isOpen: false,
|
|
2361
|
-
selected: []
|
|
2362
|
-
};
|
|
2363
|
-
|
|
2364
|
-
this.onToggle = (_event, isOpen) => {
|
|
2365
|
-
this.setState({
|
|
2366
|
-
isOpen
|
|
2367
|
-
});
|
|
2368
|
-
};
|
|
2369
|
-
|
|
2370
|
-
this.onSelect = (event, selection) => {
|
|
2371
|
-
const { selected } = this.state;
|
|
2372
|
-
if (selected.includes(selection)) {
|
|
2373
|
-
this.setState(
|
|
2374
|
-
prevState => ({ selected: prevState.selected.filter(item => item !== selection) }),
|
|
2375
|
-
() => console.log('selections: ', this.state.selected)
|
|
2376
|
-
);
|
|
2377
|
-
} else {
|
|
2378
|
-
this.setState(
|
|
2379
|
-
prevState => ({ selected: [...prevState.selected, selection] }),
|
|
2380
|
-
() => console.log('selections: ', this.state.selected)
|
|
2381
|
-
);
|
|
2382
|
-
}
|
|
2383
|
-
};
|
|
2384
|
-
|
|
2385
|
-
this.clearSelection = () => {
|
|
2386
|
-
this.setState({
|
|
2387
|
-
selected: [],
|
|
2388
|
-
isOpen: false
|
|
2389
|
-
});
|
|
2390
|
-
};
|
|
2391
|
-
}
|
|
2392
|
-
|
|
2393
|
-
render() {
|
|
2394
|
-
const { isOpen, selected, isCreatable, hasOnCreateOption } = this.state;
|
|
2395
|
-
const titleId = 'multi-typeahead-custom-chip-group-props-id-1';
|
|
2396
|
-
|
|
2397
|
-
return (
|
|
2398
|
-
<div>
|
|
2399
|
-
<span id={titleId} hidden>
|
|
2400
|
-
Select a state
|
|
2401
|
-
</span>
|
|
2402
|
-
<Select
|
|
2403
|
-
chipGroupProps={{ numChips: 1, expandedText: 'Hide', collapsedText: 'Show ${remaining}' }}
|
|
2404
|
-
variant={SelectVariant.typeaheadMulti}
|
|
2405
|
-
typeAheadAriaLabel="Select a state"
|
|
2406
|
-
onToggle={this.onToggle}
|
|
2407
|
-
onSelect={this.onSelect}
|
|
2408
|
-
onClear={this.clearSelection}
|
|
2409
|
-
selections={selected}
|
|
2410
|
-
isOpen={isOpen}
|
|
2411
|
-
aria-labelledby={titleId}
|
|
2412
|
-
placeholderText="Select a state"
|
|
2413
|
-
>
|
|
2414
|
-
{this.state.options.map((option, index) => (
|
|
2415
|
-
<SelectOption
|
|
2416
|
-
isDisabled={option.disabled}
|
|
2417
|
-
key={index}
|
|
2418
|
-
value={option.value}
|
|
2419
|
-
{...(option.description && { description: option.description })}
|
|
2420
|
-
/>
|
|
2421
|
-
))}
|
|
2422
|
-
</Select>
|
|
2423
|
-
</div>
|
|
2424
|
-
);
|
|
2425
|
-
}
|
|
2426
|
-
}
|
|
2427
|
-
```
|
|
2428
|
-
|
|
2429
|
-
### Multiple typeahead with chip group
|
|
2430
|
-
|
|
2431
|
-
To customize chips even more, render a [`<ChipGroup>`](/components/chip-group) component and pass it into the `chipGroupComponent` property of the `<Select>` component.
|
|
2432
|
-
|
|
2433
|
-
```js
|
|
2434
|
-
import React from 'react';
|
|
2435
|
-
import { Select, SelectOption, SelectVariant, ChipGroup, Chip } from '@patternfly/react-core';
|
|
2436
|
-
|
|
2437
|
-
class MultiTypeaheadSelectInputWithChipGroupProps extends React.Component {
|
|
2438
|
-
constructor(props) {
|
|
2439
|
-
super(props);
|
|
2440
|
-
|
|
2441
|
-
this.state = {
|
|
2442
|
-
options: [
|
|
2443
|
-
{ value: 'Alabama', disabled: false },
|
|
2444
|
-
{ value: 'Florida', disabled: false },
|
|
2445
|
-
{ value: 'New Jersey', disabled: false },
|
|
2446
|
-
{ value: 'New Mexico', disabled: false, description: 'This is a description' },
|
|
2447
|
-
{ value: 'New York', disabled: false },
|
|
2448
|
-
{ value: 'North Carolina', disabled: false }
|
|
2449
|
-
],
|
|
2450
|
-
isOpen: false,
|
|
2451
|
-
selected: []
|
|
2452
|
-
};
|
|
2453
|
-
|
|
2454
|
-
this.onToggle = (_event, isOpen) => {
|
|
2455
|
-
this.setState({
|
|
2456
|
-
isOpen
|
|
2457
|
-
});
|
|
2458
|
-
};
|
|
2459
|
-
|
|
2460
|
-
this.onSelect = (event, selection) => {
|
|
2461
|
-
const { selected } = this.state;
|
|
2462
|
-
if (selected.includes(selection)) {
|
|
2463
|
-
this.setState(
|
|
2464
|
-
prevState => ({ selected: prevState.selected.filter(item => item !== selection) }),
|
|
2465
|
-
() => console.log('selections: ', this.state.selected)
|
|
2466
|
-
);
|
|
2467
|
-
} else {
|
|
2468
|
-
this.setState(
|
|
2469
|
-
prevState => ({ selected: [...prevState.selected, selection] }),
|
|
2470
|
-
() => console.log('selections: ', this.state.selected)
|
|
2471
|
-
);
|
|
2472
|
-
}
|
|
2473
|
-
};
|
|
2474
|
-
|
|
2475
|
-
this.clearSelection = () => {
|
|
2476
|
-
this.setState({
|
|
2477
|
-
selected: [],
|
|
2478
|
-
isOpen: false
|
|
2479
|
-
});
|
|
2480
|
-
};
|
|
2481
|
-
this.chipGroupComponent = () => {
|
|
2482
|
-
const { selected } = this.state;
|
|
2483
|
-
return (
|
|
2484
|
-
<ChipGroup>
|
|
2485
|
-
{(selected || []).map((currentChip, index) => (
|
|
2486
|
-
<Chip
|
|
2487
|
-
isReadOnly={index === 0 ? true : false}
|
|
2488
|
-
key={currentChip}
|
|
2489
|
-
onClick={event => this.onSelect(event, currentChip)}
|
|
2490
|
-
>
|
|
2491
|
-
{currentChip}
|
|
2492
|
-
</Chip>
|
|
2493
|
-
))}
|
|
2494
|
-
</ChipGroup>
|
|
2495
|
-
);
|
|
2496
|
-
};
|
|
2497
|
-
}
|
|
2498
|
-
|
|
2499
|
-
render() {
|
|
2500
|
-
const { isOpen, selected, isCreatable, hasOnCreateOption } = this.state;
|
|
2501
|
-
const titleId = 'multi-typeahead-render-chip-group-props-id-1';
|
|
2502
|
-
|
|
2503
|
-
return (
|
|
2504
|
-
<div>
|
|
2505
|
-
<span id={titleId} hidden>
|
|
2506
|
-
Select a state
|
|
2507
|
-
</span>
|
|
2508
|
-
<Select
|
|
2509
|
-
chipGroupProps={{ numChips: 1, expandedText: 'Hide', collapsedText: 'Show ${remaining}' }}
|
|
2510
|
-
variant={SelectVariant.typeaheadMulti}
|
|
2511
|
-
typeAheadAriaLabel="Select a state"
|
|
2512
|
-
onToggle={this.onToggle}
|
|
2513
|
-
onSelect={this.onSelect}
|
|
2514
|
-
onClear={this.clearSelection}
|
|
2515
|
-
selections={selected}
|
|
2516
|
-
isOpen={isOpen}
|
|
2517
|
-
aria-labelledby={titleId}
|
|
2518
|
-
placeholderText="Select a state"
|
|
2519
|
-
chipGroupComponent={this.chipGroupComponent()}
|
|
2520
|
-
>
|
|
2521
|
-
{this.state.options.map((option, index) => (
|
|
2522
|
-
<SelectOption
|
|
2523
|
-
isDisabled={option.disabled}
|
|
2524
|
-
key={index}
|
|
2525
|
-
value={option.value}
|
|
2526
|
-
{...(option.description && { description: option.description })}
|
|
2527
|
-
/>
|
|
2528
|
-
))}
|
|
2529
|
-
</Select>
|
|
2530
|
-
</div>
|
|
2531
|
-
);
|
|
2532
|
-
}
|
|
2533
|
-
}
|
|
2534
|
-
```
|
|
2535
|
-
|
|
2536
|
-
### Multiple typeahead with custom objects
|
|
2537
|
-
|
|
2538
|
-
A `<SelectOption>` can have an object passed into the `value` property in order to store additional data beyond just a string value. The object passed in must have a `toString` function that returns a string to display in the `SelectMenu`.
|
|
2539
|
-
|
|
2540
|
-
```js
|
|
2541
|
-
import React from 'react';
|
|
2542
|
-
import { Select, SelectOption, SelectVariant, Divider } from '@patternfly/react-core';
|
|
2543
|
-
|
|
2544
|
-
class MultiTypeaheadSelectInputCustomObjects extends React.Component {
|
|
2545
|
-
constructor(props) {
|
|
2546
|
-
super(props);
|
|
2547
|
-
this.createState = (name, abbreviation, capital, founded) => {
|
|
2548
|
-
return {
|
|
2549
|
-
name: name,
|
|
2550
|
-
abbreviation: abbreviation,
|
|
2551
|
-
capital: capital,
|
|
2552
|
-
founded: founded,
|
|
2553
|
-
toString: function() {
|
|
2554
|
-
return `${this.name} (${this.abbreviation}) - Founded: ${this.founded}`;
|
|
2555
|
-
},
|
|
2556
|
-
compareTo: function(value) {
|
|
2557
|
-
return this.toString()
|
|
2558
|
-
.toLowerCase()
|
|
2559
|
-
.includes(value.toString().toLowerCase());
|
|
2560
|
-
}
|
|
2561
|
-
};
|
|
2562
|
-
};
|
|
2563
|
-
this.options = [
|
|
2564
|
-
<SelectOption key={0} value={this.createState('Alabama', 'AL', 'Montgomery', 1846)} />,
|
|
2565
|
-
<Divider component="li" key={111} />,
|
|
2566
|
-
<SelectOption key={1} value={this.createState('Florida', 'FL', 'Tailahassee', 1845)} />,
|
|
2567
|
-
<SelectOption key={2} value={this.createState('New Jersey', 'NJ', 'Trenton', 1787)} />,
|
|
2568
|
-
<SelectOption key={3} value={this.createState('New Mexico', 'NM', 'Santa Fe', 1912)} />,
|
|
2569
|
-
<SelectOption key={4} value={this.createState('New York', 'NY', 'Albany', 1788)} />,
|
|
2570
|
-
<SelectOption key={5} value={this.createState('North Carolina', 'NC', 'Raleigh', 1789)} />
|
|
2571
|
-
];
|
|
2572
|
-
|
|
2573
|
-
this.state = {
|
|
2574
|
-
isOpen: false,
|
|
2575
|
-
selected: []
|
|
2576
|
-
};
|
|
2577
|
-
|
|
2578
|
-
this.onToggle = (_event, isOpen) => {
|
|
2579
|
-
this.setState({
|
|
2580
|
-
isOpen
|
|
2581
|
-
});
|
|
2582
|
-
};
|
|
2583
|
-
|
|
2584
|
-
this.onSelect = (event, selection) => {
|
|
2585
|
-
const { selected } = this.state;
|
|
2586
|
-
if (selected.includes(selection)) {
|
|
2587
|
-
this.setState(
|
|
2588
|
-
prevState => ({ selected: prevState.selected.filter(item => item !== selection) }),
|
|
2589
|
-
() => console.log('selections: ', this.state.selected)
|
|
2590
|
-
);
|
|
2591
|
-
} else {
|
|
2592
|
-
this.setState(
|
|
2593
|
-
prevState => ({ selected: [...prevState.selected, selection] }),
|
|
2594
|
-
() => console.log('selections: ', this.state.selected)
|
|
2595
|
-
);
|
|
2596
|
-
}
|
|
2597
|
-
};
|
|
2598
|
-
|
|
2599
|
-
this.clearSelection = () => {
|
|
2600
|
-
this.setState({
|
|
2601
|
-
selected: [],
|
|
2602
|
-
isOpen: false
|
|
2603
|
-
});
|
|
2604
|
-
};
|
|
2605
|
-
}
|
|
2606
|
-
|
|
2607
|
-
render() {
|
|
2608
|
-
const { isOpen, selected } = this.state;
|
|
2609
|
-
const titleId = 'multi-typeahead-select-id-2';
|
|
2610
|
-
|
|
2611
|
-
return (
|
|
2612
|
-
<div>
|
|
2613
|
-
<span id={titleId} hidden>
|
|
2614
|
-
Select a state
|
|
2615
|
-
</span>
|
|
2616
|
-
<Select
|
|
2617
|
-
variant={SelectVariant.typeaheadMulti}
|
|
2618
|
-
typeAheadAriaLabel="Select a state"
|
|
2619
|
-
onToggle={this.onToggle}
|
|
2620
|
-
onSelect={this.onSelect}
|
|
2621
|
-
onClear={this.clearSelection}
|
|
2622
|
-
onFilter={this.customFilter}
|
|
2623
|
-
selections={selected}
|
|
2624
|
-
isOpen={isOpen}
|
|
2625
|
-
aria-labelledby={titleId}
|
|
2626
|
-
placeholderText="Select a state"
|
|
2627
|
-
>
|
|
2628
|
-
{this.options}
|
|
2629
|
-
</Select>
|
|
2630
|
-
</div>
|
|
2631
|
-
);
|
|
2632
|
-
}
|
|
2633
|
-
}
|
|
2634
|
-
```
|
|
2635
|
-
|
|
2636
|
-
### Plain multiple typeahead
|
|
2637
|
-
|
|
2638
|
-
To plainly style a typeahead, use the `isPlain` property.
|
|
2639
|
-
|
|
2640
|
-
```js
|
|
2641
|
-
import React from 'react';
|
|
2642
|
-
import { Select, SelectOption, SelectVariant } from '@patternfly/react-core';
|
|
2643
|
-
|
|
2644
|
-
class PlainSelectInput extends React.Component {
|
|
2645
|
-
constructor(props) {
|
|
2646
|
-
super(props);
|
|
2647
|
-
this.options = [
|
|
2648
|
-
{ value: 'Alabama', disabled: false },
|
|
2649
|
-
{ value: 'Florida', disabled: false },
|
|
2650
|
-
{ value: 'New Jersey', disabled: false },
|
|
2651
|
-
{ value: 'New Mexico', disabled: false },
|
|
2652
|
-
{ value: 'New York', disabled: false },
|
|
2653
|
-
{ value: 'North Carolina', disabled: false }
|
|
2654
|
-
];
|
|
2655
|
-
|
|
2656
|
-
this.state = {
|
|
2657
|
-
isOpen: false,
|
|
2658
|
-
isPlain: true,
|
|
2659
|
-
selected: []
|
|
2660
|
-
};
|
|
2661
|
-
|
|
2662
|
-
this.onToggle = (_event, isOpen) => {
|
|
2663
|
-
this.setState({
|
|
2664
|
-
isOpen
|
|
2665
|
-
});
|
|
2666
|
-
};
|
|
2667
|
-
|
|
2668
|
-
this.onSelect = (event, selection) => {
|
|
2669
|
-
const { selected } = this.state;
|
|
2670
|
-
if (selected.includes(selection)) {
|
|
2671
|
-
this.setState(
|
|
2672
|
-
prevState => ({ selected: prevState.selected.filter(item => item !== selection) }),
|
|
2673
|
-
() => console.log('selections: ', this.state.selected)
|
|
2674
|
-
);
|
|
2675
|
-
} else {
|
|
2676
|
-
this.setState(
|
|
2677
|
-
prevState => ({ selected: [...prevState.selected, selection] }),
|
|
2678
|
-
() => console.log('selections: ', this.state.selected)
|
|
2679
|
-
);
|
|
2680
|
-
}
|
|
2681
|
-
};
|
|
2682
|
-
|
|
2683
|
-
this.clearSelection = () => {
|
|
2684
|
-
this.setState({
|
|
2685
|
-
selected: [],
|
|
2686
|
-
isOpen: false
|
|
2687
|
-
});
|
|
2688
|
-
};
|
|
2689
|
-
}
|
|
2690
|
-
|
|
2691
|
-
render() {
|
|
2692
|
-
const { isOpen, isPlain, selected } = this.state;
|
|
2693
|
-
const titleId = 'plain-typeahead-select-id';
|
|
2694
|
-
|
|
2695
|
-
return (
|
|
2696
|
-
<div>
|
|
2697
|
-
<span id={titleId} hidden>
|
|
2698
|
-
Select a state
|
|
2699
|
-
</span>
|
|
2700
|
-
<Select
|
|
2701
|
-
variant={SelectVariant.typeaheadMulti}
|
|
2702
|
-
typeAheadAriaLabel="Select a state"
|
|
2703
|
-
onToggle={this.onToggle}
|
|
2704
|
-
onSelect={this.onSelect}
|
|
2705
|
-
onClear={this.clearSelection}
|
|
2706
|
-
selections={selected}
|
|
2707
|
-
isOpen={isOpen}
|
|
2708
|
-
isPlain={isPlain}
|
|
2709
|
-
aria-labelledby={titleId}
|
|
2710
|
-
placeholderText="Select a state"
|
|
2711
|
-
>
|
|
2712
|
-
{this.options.map((option, index) => (
|
|
2713
|
-
<SelectOption isDisabled={option.disabled} key={index} value={option.value} />
|
|
2714
|
-
))}
|
|
2715
|
-
</Select>
|
|
2716
|
-
</div>
|
|
2717
|
-
);
|
|
2718
|
-
}
|
|
2719
|
-
}
|
|
2720
|
-
```
|
|
2721
|
-
|
|
2722
|
-
### Custom menu content
|
|
2723
|
-
|
|
2724
|
-
To add custom menu content, use the `customContent` property.
|
|
2725
|
-
|
|
2726
|
-
```js
|
|
2727
|
-
import React from 'react';
|
|
2728
|
-
import CubeIcon from '@patternfly/react-icons/dist/esm/icons/cube-icon';
|
|
2729
|
-
import { Select, SelectOption, SelectDirection, Checkbox } from '@patternfly/react-core';
|
|
2730
|
-
|
|
2731
|
-
class SingleSelectInput extends React.Component {
|
|
2732
|
-
constructor(props) {
|
|
2733
|
-
super(props);
|
|
2734
|
-
this.state = {
|
|
2735
|
-
isOpen: false,
|
|
2736
|
-
isDisabled: false,
|
|
2737
|
-
direction: SelectDirection.down
|
|
2738
|
-
};
|
|
2739
|
-
|
|
2740
|
-
this.onToggle = (_event, isOpen) => {
|
|
2741
|
-
this.setState({
|
|
2742
|
-
isOpen
|
|
2743
|
-
});
|
|
2744
|
-
};
|
|
2745
|
-
|
|
2746
|
-
this.toggleDisabled = checked => {
|
|
2747
|
-
this.setState({
|
|
2748
|
-
isDisabled: checked
|
|
2749
|
-
});
|
|
2750
|
-
};
|
|
2751
|
-
|
|
2752
|
-
this.toggleDirection = () => {
|
|
2753
|
-
if (this.state.direction === SelectDirection.up) {
|
|
2754
|
-
this.setState({
|
|
2755
|
-
direction: SelectDirection.down
|
|
2756
|
-
});
|
|
2757
|
-
} else {
|
|
2758
|
-
this.setState({
|
|
2759
|
-
direction: SelectDirection.up
|
|
2760
|
-
});
|
|
2761
|
-
}
|
|
2762
|
-
};
|
|
2763
|
-
}
|
|
2764
|
-
|
|
2765
|
-
render() {
|
|
2766
|
-
const { isOpen, selected, isDisabled, direction } = this.state;
|
|
2767
|
-
const titleId = 'title-id-2';
|
|
2768
|
-
return (
|
|
2769
|
-
<div>
|
|
2770
|
-
<span id={titleId} hidden>
|
|
2771
|
-
Title
|
|
2772
|
-
</span>
|
|
2773
|
-
<Select
|
|
2774
|
-
aria-label="Select Input"
|
|
2775
|
-
onToggle={this.onToggle}
|
|
2776
|
-
isOpen={isOpen}
|
|
2777
|
-
aria-labelledby={titleId}
|
|
2778
|
-
isDisabled={isDisabled}
|
|
2779
|
-
direction={direction}
|
|
2780
|
-
customContent="[Panel contents here]"
|
|
2781
|
-
placeholderText="Filter by birth month"
|
|
2782
|
-
/>
|
|
2783
|
-
<Checkbox
|
|
2784
|
-
label="isDisabled"
|
|
2785
|
-
isChecked={this.state.isDisabled}
|
|
2786
|
-
onChange={(_event, checked) => this.toggleDisabled(checked)}
|
|
2787
|
-
aria-label="disabled checkbox panel"
|
|
2788
|
-
id="toggle-disabled-panel"
|
|
2789
|
-
name="toggle-disabled-panel"
|
|
2790
|
-
/>
|
|
2791
|
-
<Checkbox
|
|
2792
|
-
label="Expands up"
|
|
2793
|
-
isChecked={direction === SelectDirection.up}
|
|
2794
|
-
onChange={this.toggleDirection}
|
|
2795
|
-
aria-label="direction checkbox panel"
|
|
2796
|
-
id="toggle-direction-panel"
|
|
2797
|
-
name="toggle-direction-panel"
|
|
2798
|
-
/>
|
|
2799
|
-
</div>
|
|
2800
|
-
);
|
|
2801
|
-
}
|
|
2802
|
-
}
|
|
2803
|
-
```
|
|
2804
|
-
|
|
2805
|
-
### Appending document body vs parent
|
|
2806
|
-
|
|
2807
|
-
Avoid passing in `document.body` to the `menuAppendTo` property. Doing so can cause accessibility issues because this prevents users from being able to enter the contents of the select options via assistive technologies (like keyboards or screen readers). Instead, pass in `parent` to achieve the same result without sacrificing accessibility.
|
|
2808
|
-
|
|
2809
|
-
The following example demonstrates both methods. When the dropdown is opened, both select variants manage focus the same way, but behave differently when the tab key is pressed after an option is selected.
|
|
2810
|
-
|
|
2811
|
-
- For the `document.body` variant, the focus will be placed at the end of the page, since that is where the dropdown content is appended to in the DOM (rather than focus being placed on the second Select variant as one might expect).
|
|
2812
|
-
- For the `parent` variant, however, the focus will be placed on the next tab-able element (the "Toggle JS code" button for the code editor in this case).
|
|
2813
|
-
|
|
2814
|
-
```js
|
|
2815
|
-
import React from 'react';
|
|
2816
|
-
import { Select, SelectOption, Flex, FlexItem } from '@patternfly/react-core';
|
|
2817
|
-
|
|
2818
|
-
class SelectDocumentBodyVsParent extends React.Component {
|
|
2819
|
-
constructor(props) {
|
|
2820
|
-
super(props);
|
|
2821
|
-
this.bodyOptions = [
|
|
2822
|
-
<SelectOption key={0} value="Select a title - document body" isPlaceholder />,
|
|
2823
|
-
<SelectOption key={1} value="Mr" />,
|
|
2824
|
-
<SelectOption key={2} value="Miss" />,
|
|
2825
|
-
<SelectOption key={3} value="Mrs" />,
|
|
2826
|
-
<SelectOption key={4} value="Ms" />,
|
|
2827
|
-
<SelectOption key={6} value="Dr" />,
|
|
2828
|
-
<SelectOption key={7} value="Other" />
|
|
2829
|
-
];
|
|
2830
|
-
|
|
2831
|
-
this.parentOptions = [
|
|
2832
|
-
<SelectOption key={0} value="Select a title - parent" isPlaceholder />,
|
|
2833
|
-
<SelectOption key={1} value="Mr" />,
|
|
2834
|
-
<SelectOption key={2} value="Miss" />,
|
|
2835
|
-
<SelectOption key={3} value="Mrs" />,
|
|
2836
|
-
<SelectOption key={4} value="Ms" />,
|
|
2837
|
-
<SelectOption key={6} value="Dr" />,
|
|
2838
|
-
<SelectOption key={7} value="Other" />
|
|
2839
|
-
];
|
|
2840
|
-
|
|
2841
|
-
this.state = {
|
|
2842
|
-
isBodyOpen: false,
|
|
2843
|
-
isParentOpen: false,
|
|
2844
|
-
bodySelected: null,
|
|
2845
|
-
parentSelected: null
|
|
2846
|
-
};
|
|
2847
|
-
|
|
2848
|
-
this.onBodyToggle = (_event, isBodyOpen) => {
|
|
2849
|
-
this.setState({
|
|
2850
|
-
isBodyOpen
|
|
2851
|
-
});
|
|
2852
|
-
};
|
|
2853
|
-
|
|
2854
|
-
this.onParentToggle = (_event, isParentOpen) => {
|
|
2855
|
-
this.setState({
|
|
2856
|
-
isParentOpen
|
|
2857
|
-
});
|
|
2858
|
-
};
|
|
2859
|
-
|
|
2860
|
-
this.onBodySelect = (event, selection, isPlaceholder) => {
|
|
2861
|
-
if (isPlaceholder) this.clearSelection();
|
|
2862
|
-
else {
|
|
2863
|
-
this.setState({
|
|
2864
|
-
bodySelected: selection,
|
|
2865
|
-
isBodyOpen: false
|
|
2866
|
-
});
|
|
2867
|
-
console.log('selected on document body:', selection);
|
|
2868
|
-
}
|
|
2869
|
-
};
|
|
2870
|
-
|
|
2871
|
-
this.onParentSelect = (event, selection, isPlaceholder) => {
|
|
2872
|
-
if (isPlaceholder) this.clearSelection();
|
|
2873
|
-
else {
|
|
2874
|
-
this.setState({
|
|
2875
|
-
parentSelected: selection,
|
|
2876
|
-
isParentOpen: false
|
|
2877
|
-
});
|
|
2878
|
-
console.log('selected on parent:', selection);
|
|
2879
|
-
}
|
|
2880
|
-
};
|
|
2881
|
-
|
|
2882
|
-
this.clearSelection = () => {
|
|
2883
|
-
this.setState({
|
|
2884
|
-
selected: null,
|
|
2885
|
-
isOpen: false
|
|
2886
|
-
});
|
|
2887
|
-
};
|
|
2888
|
-
}
|
|
2889
|
-
|
|
2890
|
-
render() {
|
|
2891
|
-
const { isBodyOpen, isParentOpen, bodySelected, parentSelected } = this.state;
|
|
34
|
+
### Multiple Typeahead
|
|
2892
35
|
|
|
2893
|
-
|
|
2894
|
-
<Flex space={{ default: 'spacerMd' }} direction={{ default: 'column' }}>
|
|
2895
|
-
<FlexItem>
|
|
2896
|
-
<Select
|
|
2897
|
-
aria-label="Select Input for Document Body"
|
|
2898
|
-
onToggle={this.onBodyToggle}
|
|
2899
|
-
onSelect={this.onBodySelect}
|
|
2900
|
-
selections={bodySelected}
|
|
2901
|
-
isOpen={isBodyOpen}
|
|
2902
|
-
menuAppendTo={() => document.body}
|
|
2903
|
-
>
|
|
2904
|
-
{this.bodyOptions}
|
|
2905
|
-
</Select>
|
|
2906
|
-
</FlexItem>
|
|
2907
|
-
<FlexItem>
|
|
2908
|
-
<Select
|
|
2909
|
-
aria-label="Select Input for Parent"
|
|
2910
|
-
onToggle={this.onParentToggle}
|
|
2911
|
-
onSelect={this.onParentSelect}
|
|
2912
|
-
selections={parentSelected}
|
|
2913
|
-
isOpen={isParentOpen}
|
|
2914
|
-
menuAppendTo="parent"
|
|
2915
|
-
>
|
|
2916
|
-
{this.parentOptions}
|
|
2917
|
-
</Select>
|
|
2918
|
-
</FlexItem>
|
|
2919
|
-
</Flex>
|
|
2920
|
-
);
|
|
2921
|
-
}
|
|
2922
|
-
}
|
|
36
|
+
```ts file="./SelectMultiTypeahead.tsx"
|
|
2923
37
|
```
|