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,
|
useMultiList,
|
||||||
useSingleList,
|
useSingleList,
|
||||||
useRemoteList,
|
useRemoteList,
|
||||||
|
useOnFormReset,
|
||||||
createLoader,
|
createLoader,
|
||||||
type ComboBoxProps
|
type ComboBoxProps
|
||||||
} from './react-aria/hooks';
|
} from './react-aria/hooks';
|
||||||
|
@ -102,7 +103,7 @@ export function SingleComboBox({
|
||||||
const labelledby = useLabelledBy(props.id, ariaLabelledby);
|
const labelledby = useLabelledBy(props.id, ariaLabelledby);
|
||||||
const { ref, dispatch } = useDispatchChangeEvent();
|
const { ref, dispatch } = useDispatchChangeEvent();
|
||||||
|
|
||||||
const { selectedItem, ...comboBoxProps } = useSingleList({
|
const { selectedItem, onReset, ...comboBoxProps } = useSingleList({
|
||||||
defaultItems,
|
defaultItems,
|
||||||
defaultSelectedKey,
|
defaultSelectedKey,
|
||||||
emptyFilterKey,
|
emptyFilterKey,
|
||||||
|
@ -122,6 +123,7 @@ export function SingleComboBox({
|
||||||
field={formValue == 'text' ? 'label' : 'value'}
|
field={formValue == 'text' ? 'label' : 'value'}
|
||||||
name={name}
|
name={name}
|
||||||
form={form}
|
form={form}
|
||||||
|
onReset={onReset}
|
||||||
data={data}
|
data={data}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
@ -150,8 +152,13 @@ export function MultiComboBox(maybeProps: MultiComboBoxProps) {
|
||||||
const { ref, dispatch } = useDispatchChangeEvent();
|
const { ref, dispatch } = useDispatchChangeEvent();
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
const { selectedItems, hiddenInputValues, onRemove, ...comboBoxProps } =
|
const {
|
||||||
useMultiList({
|
selectedItems,
|
||||||
|
hiddenInputValues,
|
||||||
|
onRemove,
|
||||||
|
onReset,
|
||||||
|
...comboBoxProps
|
||||||
|
} = useMultiList({
|
||||||
defaultItems,
|
defaultItems,
|
||||||
defaultSelectedKeys,
|
defaultSelectedKeys,
|
||||||
onChange: dispatch,
|
onChange: dispatch,
|
||||||
|
@ -162,6 +169,7 @@ export function MultiComboBox(maybeProps: MultiComboBoxProps) {
|
||||||
inputRef.current?.focus();
|
inputRef.current?.focus();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
const formResetRef = useOnFormReset(onReset);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fr-ds-combobox__multiple">
|
<div className="fr-ds-combobox__multiple">
|
||||||
|
@ -193,12 +201,13 @@ export function MultiComboBox(maybeProps: MultiComboBoxProps) {
|
||||||
</ComboBox>
|
</ComboBox>
|
||||||
{name ? (
|
{name ? (
|
||||||
<span ref={ref}>
|
<span ref={ref}>
|
||||||
{hiddenInputValues.map((value) => (
|
{hiddenInputValues.map((value, i) => (
|
||||||
<input
|
<input
|
||||||
type="hidden"
|
type="hidden"
|
||||||
value={value}
|
value={value}
|
||||||
name={name}
|
name={name}
|
||||||
form={form}
|
form={form}
|
||||||
|
ref={i == 0 ? formResetRef : undefined}
|
||||||
key={value}
|
key={value}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
@ -238,7 +247,7 @@ export function RemoteComboBox({
|
||||||
: loader,
|
: loader,
|
||||||
[loader, minimumInputLength, limit]
|
[loader, minimumInputLength, limit]
|
||||||
);
|
);
|
||||||
const { selectedItem, ...comboBoxProps } = useRemoteList({
|
const { selectedItem, onReset, ...comboBoxProps } = useRemoteList({
|
||||||
allowsCustomValue,
|
allowsCustomValue,
|
||||||
defaultItems,
|
defaultItems,
|
||||||
defaultSelectedKey,
|
defaultSelectedKey,
|
||||||
|
@ -270,6 +279,7 @@ export function RemoteComboBox({
|
||||||
}
|
}
|
||||||
name={name}
|
name={name}
|
||||||
form={form}
|
form={form}
|
||||||
|
onReset={onReset}
|
||||||
data={data}
|
data={data}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
@ -285,11 +295,13 @@ export function ComboBoxValueSlot({
|
||||||
field,
|
field,
|
||||||
name,
|
name,
|
||||||
form,
|
form,
|
||||||
|
onReset,
|
||||||
data
|
data
|
||||||
}: {
|
}: {
|
||||||
field: 'label' | 'value' | 'data';
|
field: 'label' | 'value' | 'data';
|
||||||
name: string;
|
name: string;
|
||||||
form?: string;
|
form?: string;
|
||||||
|
onReset?: () => void;
|
||||||
data?: Record<string, string>;
|
data?: Record<string, string>;
|
||||||
}) {
|
}) {
|
||||||
const selectedItem = useContext(SelectedItemContext);
|
const selectedItem = useContext(SelectedItemContext);
|
||||||
|
@ -300,8 +312,16 @@ export function ComboBoxValueSlot({
|
||||||
value
|
value
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
const ref = useOnFormReset(onReset);
|
||||||
return (
|
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
|
// reset default selected key when props change
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -122,7 +126,8 @@ export function useSingleList({
|
||||||
onSelectionChange,
|
onSelectionChange,
|
||||||
inputValue,
|
inputValue,
|
||||||
onInputChange,
|
onInputChange,
|
||||||
items: filteredItems
|
items: filteredItems,
|
||||||
|
onReset
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,6 +277,11 @@ export function useMultiList({
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const onReset = useEvent(() => {
|
||||||
|
setSelectedKeys(new Set());
|
||||||
|
setInputValue('');
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
onRemove,
|
onRemove,
|
||||||
onSelectionChange,
|
onSelectionChange,
|
||||||
|
@ -279,7 +289,8 @@ export function useMultiList({
|
||||||
selectedItems,
|
selectedItems,
|
||||||
items: filteredItems,
|
items: filteredItems,
|
||||||
hiddenInputValues,
|
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
|
// add to items list current selected item if it's not in the list
|
||||||
const items =
|
const items =
|
||||||
selectedItem && !list.getItem(selectedItem.value)
|
selectedItem && !list.getItem(selectedItem.value)
|
||||||
|
@ -369,7 +385,8 @@ export function useRemoteList({
|
||||||
onSelectionChange,
|
onSelectionChange,
|
||||||
inputValue,
|
inputValue,
|
||||||
onInputChange,
|
onInputChange,
|
||||||
items
|
items,
|
||||||
|
onReset
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,3 +453,22 @@ function findLabelledbyId(id?: string) {
|
||||||
}
|
}
|
||||||
return label.id;
|
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