feat(combobox): reset value on form reset
This commit is contained in:
parent
89fb0abe6e
commit
c6f1d16451
2 changed files with 75 additions and 19 deletions
|
@ -22,6 +22,7 @@ import {
|
|||
useMultiList,
|
||||
useSingleList,
|
||||
useRemoteList,
|
||||
useOnFormReset,
|
||||
createLoader,
|
||||
type ComboBoxProps
|
||||
} from './react-aria/hooks';
|
||||
|
@ -102,7 +103,7 @@ export function SingleComboBox({
|
|||
const labelledby = useLabelledBy(props.id, ariaLabelledby);
|
||||
const { ref, dispatch } = useDispatchChangeEvent();
|
||||
|
||||
const { selectedItem, ...comboBoxProps } = useSingleList({
|
||||
const { selectedItem, onReset, ...comboBoxProps } = useSingleList({
|
||||
defaultItems,
|
||||
defaultSelectedKey,
|
||||
emptyFilterKey,
|
||||
|
@ -122,6 +123,7 @@ export function SingleComboBox({
|
|||
field={formValue == 'text' ? 'label' : 'value'}
|
||||
name={name}
|
||||
form={form}
|
||||
onReset={onReset}
|
||||
data={data}
|
||||
/>
|
||||
) : null}
|
||||
|
@ -150,18 +152,24 @@ export function MultiComboBox(maybeProps: MultiComboBoxProps) {
|
|||
const { ref, dispatch } = useDispatchChangeEvent();
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const { selectedItems, hiddenInputValues, onRemove, ...comboBoxProps } =
|
||||
useMultiList({
|
||||
defaultItems,
|
||||
defaultSelectedKeys,
|
||||
onChange: dispatch,
|
||||
formValue,
|
||||
allowsCustomValue,
|
||||
valueSeparator,
|
||||
focusInput: () => {
|
||||
inputRef.current?.focus();
|
||||
}
|
||||
});
|
||||
const {
|
||||
selectedItems,
|
||||
hiddenInputValues,
|
||||
onRemove,
|
||||
onReset,
|
||||
...comboBoxProps
|
||||
} = useMultiList({
|
||||
defaultItems,
|
||||
defaultSelectedKeys,
|
||||
onChange: dispatch,
|
||||
formValue,
|
||||
allowsCustomValue,
|
||||
valueSeparator,
|
||||
focusInput: () => {
|
||||
inputRef.current?.focus();
|
||||
}
|
||||
});
|
||||
const formResetRef = useOnFormReset(onReset);
|
||||
|
||||
return (
|
||||
<div className="fr-ds-combobox__multiple">
|
||||
|
@ -193,12 +201,13 @@ export function MultiComboBox(maybeProps: MultiComboBoxProps) {
|
|||
</ComboBox>
|
||||
{name ? (
|
||||
<span ref={ref}>
|
||||
{hiddenInputValues.map((value) => (
|
||||
{hiddenInputValues.map((value, i) => (
|
||||
<input
|
||||
type="hidden"
|
||||
value={value}
|
||||
name={name}
|
||||
form={form}
|
||||
ref={i == 0 ? formResetRef : undefined}
|
||||
key={value}
|
||||
/>
|
||||
))}
|
||||
|
@ -238,7 +247,7 @@ export function RemoteComboBox({
|
|||
: loader,
|
||||
[loader, minimumInputLength, limit]
|
||||
);
|
||||
const { selectedItem, ...comboBoxProps } = useRemoteList({
|
||||
const { selectedItem, onReset, ...comboBoxProps } = useRemoteList({
|
||||
allowsCustomValue,
|
||||
defaultItems,
|
||||
defaultSelectedKey,
|
||||
|
@ -270,6 +279,7 @@ export function RemoteComboBox({
|
|||
}
|
||||
name={name}
|
||||
form={form}
|
||||
onReset={onReset}
|
||||
data={data}
|
||||
/>
|
||||
) : null}
|
||||
|
@ -285,11 +295,13 @@ export function ComboBoxValueSlot({
|
|||
field,
|
||||
name,
|
||||
form,
|
||||
onReset,
|
||||
data
|
||||
}: {
|
||||
field: 'label' | 'value' | 'data';
|
||||
name: string;
|
||||
form?: string;
|
||||
onReset?: () => void;
|
||||
data?: Record<string, string>;
|
||||
}) {
|
||||
const selectedItem = useContext(SelectedItemContext);
|
||||
|
@ -300,8 +312,16 @@ export function ComboBoxValueSlot({
|
|||
value
|
||||
])
|
||||
);
|
||||
const ref = useOnFormReset(onReset);
|
||||
return (
|
||||
<input type="hidden" name={name} value={value} form={form} {...dataProps} />
|
||||
<input
|
||||
ref={onReset ? ref : undefined}
|
||||
type="hidden"
|
||||
name={name}
|
||||
value={value}
|
||||
form={form}
|
||||
{...dataProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -107,6 +107,10 @@ export function useSingleList({
|
|||
}
|
||||
}
|
||||
);
|
||||
const onReset = useEvent(() => {
|
||||
setSelectedKey(null);
|
||||
setInputValue('');
|
||||
});
|
||||
|
||||
// reset default selected key when props change
|
||||
useEffect(() => {
|
||||
|
@ -122,7 +126,8 @@ export function useSingleList({
|
|||
onSelectionChange,
|
||||
inputValue,
|
||||
onInputChange,
|
||||
items: filteredItems
|
||||
items: filteredItems,
|
||||
onReset
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -272,6 +277,11 @@ export function useMultiList({
|
|||
}
|
||||
);
|
||||
|
||||
const onReset = useEvent(() => {
|
||||
setSelectedKeys(new Set());
|
||||
setInputValue('');
|
||||
});
|
||||
|
||||
return {
|
||||
onRemove,
|
||||
onSelectionChange,
|
||||
|
@ -279,7 +289,8 @@ export function useMultiList({
|
|||
selectedItems,
|
||||
items: filteredItems,
|
||||
hiddenInputValues,
|
||||
inputValue
|
||||
inputValue,
|
||||
onReset
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -357,6 +368,11 @@ export function useRemoteList({
|
|||
}
|
||||
);
|
||||
|
||||
const onReset = useEvent(() => {
|
||||
setSelectedItem(null);
|
||||
setInputValue('');
|
||||
});
|
||||
|
||||
// add to items list current selected item if it's not in the list
|
||||
const items =
|
||||
selectedItem && !list.getItem(selectedItem.value)
|
||||
|
@ -369,7 +385,8 @@ export function useRemoteList({
|
|||
onSelectionChange,
|
||||
inputValue,
|
||||
onInputChange,
|
||||
items
|
||||
items,
|
||||
onReset
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -436,3 +453,22 @@ function findLabelledbyId(id?: string) {
|
|||
}
|
||||
return label.id;
|
||||
}
|
||||
|
||||
export function useOnFormReset(onReset?: () => void) {
|
||||
const ref = useRef<HTMLInputElement>(null);
|
||||
const onResetListener = useEvent<EventListener>((event) => {
|
||||
if (event.target == ref.current?.form) {
|
||||
onReset?.();
|
||||
}
|
||||
});
|
||||
useEffect(() => {
|
||||
if (onReset) {
|
||||
addEventListener('reset', onResetListener);
|
||||
return () => {
|
||||
removeEventListener('reset', onResetListener);
|
||||
};
|
||||
}
|
||||
}, [onReset, onResetListener]);
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue