Skip to content

Commit 12c4579

Browse files
jeff-phillips-18tlabaj
authored andcommitted
fix(TypeaheadSelect): Add callback on clear selection (patternfly#10719)
1 parent c07aa26 commit 12c4579

File tree

2 files changed

+44
-14
lines changed

2 files changed

+44
-14
lines changed

packages/react-templates/src/components/Select/TypeaheadSelect.tsx

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ export interface TypeaheadSelectProps extends Omit<SelectProps, 'toggle'> {
3636
onToggle?: (nextIsOpen: boolean) => void;
3737
/** Callback triggered when the text in the input field changes. */
3838
onInputChange?: (newValue: string) => void;
39+
/** Callback triggered when the clear button is selected */
40+
onClearSelection?: () => void;
3941
/** Placeholder text for the select input. */
4042
placeholder?: string;
4143
/** Message to display when no options match the filter. */
@@ -54,6 +56,7 @@ export const TypeaheadSelectBase: React.FunctionComponent<TypeaheadSelectProps>
5456
onSelect,
5557
onToggle,
5658
onInputChange,
59+
onClearSelection,
5760
placeholder = 'Select an option',
5861
noOptionsFoundMessage = (filter) => `No results found for "${filter}"`,
5962
isDisabled,
@@ -62,8 +65,10 @@ export const TypeaheadSelectBase: React.FunctionComponent<TypeaheadSelectProps>
6265
...props
6366
}: TypeaheadSelectProps) => {
6467
const [isOpen, setIsOpen] = React.useState(false);
65-
const [selected, setSelected] = React.useState<string>('');
66-
const [inputValue, setInputValue] = React.useState<string>('');
68+
const [selected, setSelected] = React.useState<string>(String(initialOptions.find((o) => o.selected)?.content ?? ''));
69+
const [inputValue, setInputValue] = React.useState<string>(
70+
String(initialOptions.find((o) => o.selected)?.content ?? '')
71+
);
6772
const [filterValue, setFilterValue] = React.useState<string>('');
6873
const [selectOptions, setSelectOptions] = React.useState<TypeaheadSelectOption[]>(initialOptions);
6974
const [focusedItemIndex, setFocusedItemIndex] = React.useState<number | null>(null);
@@ -102,6 +107,16 @@ export const TypeaheadSelectBase: React.FunctionComponent<TypeaheadSelectProps>
102107
setSelectOptions(newSelectOptions);
103108
}, [filterValue, initialOptions]);
104109

110+
React.useEffect(() => {
111+
const selectedOption = initialOptions.find((o) => o.selected);
112+
if (selectedOption?.value !== selected) {
113+
setInputValue(String(selectedOption?.content ?? ''));
114+
setSelected(String(selectedOption?.content ?? ''));
115+
}
116+
// Do not update when selected changes, only if the given options have changed
117+
// eslint-disable-next-line react-hooks/exhaustive-deps
118+
}, [initialOptions]);
119+
105120
const setActiveAndFocusedItem = (itemIndex: number) => {
106121
setFocusedItemIndex(itemIndex);
107122
const focusedItem = selectOptions[itemIndex];
@@ -122,6 +137,10 @@ export const TypeaheadSelectBase: React.FunctionComponent<TypeaheadSelectProps>
122137
onToggle && onToggle(false);
123138
setIsOpen(false);
124139
resetActiveAndFocusedItem();
140+
const option = initialOptions.find((o) => o.value === selected);
141+
if (option) {
142+
setInputValue(String(option.content));
143+
}
125144
};
126145

127146
const onInputClick = () => {
@@ -158,10 +177,6 @@ export const TypeaheadSelectBase: React.FunctionComponent<TypeaheadSelectProps>
158177
setFilterValue(value);
159178

160179
resetActiveAndFocusedItem();
161-
162-
if (value !== selected) {
163-
setSelected('');
164-
}
165180
};
166181

167182
const handleMenuArrowKeys = (key: string) => {
@@ -248,6 +263,7 @@ export const TypeaheadSelectBase: React.FunctionComponent<TypeaheadSelectProps>
248263
setFilterValue('');
249264
resetActiveAndFocusedItem();
250265
textInputRef?.current?.focus();
266+
onClearSelection && onClearSelection();
251267
};
252268

253269
const toggle = (toggleRef: React.Ref<MenuToggleElement>) => (
Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,35 @@
11
import React from 'react';
22
import { TypeaheadSelect, TypeaheadSelectOption } from '@patternfly/react-templates';
33

4+
const Options = [
5+
{ content: 'Alabama', value: 'option1' },
6+
{ content: 'Florida', value: 'option2' },
7+
{ content: 'New Jersey', value: 'option3' },
8+
{ content: 'New Mexico', value: 'option4' },
9+
{ content: 'New York', value: 'option5' },
10+
{ content: 'North Carolina', value: 'option6' }
11+
];
12+
13+
/* eslint-disable no-console */
414
export const SelectTypeaheadDemo: React.FunctionComponent = () => {
5-
const initialOptions: TypeaheadSelectOption[] = [
6-
{ content: 'Alabama', value: 'option1' },
7-
{ content: 'Florida', value: 'option2' },
8-
{ content: 'New Jersey', value: 'option3' },
9-
{ content: 'New Mexico', value: 'option4' },
10-
{ content: 'New York', value: 'option5' },
11-
{ content: 'North Carolina', value: 'option6' }
12-
];
15+
const [selected, setSelected] = React.useState<string | undefined>();
16+
17+
const initialOptions = React.useMemo<TypeaheadSelectOption[]>(
18+
() => Options.map((o) => ({ ...o, selected: o.value === selected })),
19+
[selected]
20+
);
21+
22+
React.useEffect(() => {
23+
console.log(`Selected: ${selected || 'none'}`);
24+
}, [selected]);
1325

1426
return (
1527
<TypeaheadSelect
1628
initialOptions={initialOptions}
1729
placeholder="Select a state"
1830
noOptionsFoundMessage={(filter) => `No state was found for "${filter}"`}
31+
onClearSelection={() => setSelected(undefined)}
32+
onSelect={(_ev, selection) => setSelected(String(selection))}
1933
/>
2034
);
2135
};

0 commit comments

Comments
 (0)