Skip to content

Commit

Permalink
Add allowDuplicates for AutocompleteArrayInput
Browse files Browse the repository at this point in the history
  • Loading branch information
alanpoulain committed Nov 22, 2019
1 parent 6194bbb commit d5da818
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 15 deletions.
14 changes: 14 additions & 0 deletions packages/ra-core/src/form/useSuggestions.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,18 @@ describe('getSuggestions', () => {
expect(getSuggestions(defaultOptions)(false)).toEqual(choices);
expect(getSuggestions(defaultOptions)(null)).toEqual(choices);
});

it('should return all choices if allowDuplicates is true', () => {
expect(
getSuggestions({
...defaultOptions,
allowDuplicates: true,
selectedItem: choices[0],
})('')
).toEqual([
{ id: 1, value: 'one' },
{ id: 2, value: 'two' },
{ id: 3, value: 'three' },
]);
});
});
27 changes: 16 additions & 11 deletions packages/ra-core/src/form/useSuggestions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useTranslate } from '../i18n';
/*
* Returns helper functions for suggestions handling.
*
* @param allowDuplicates A boolean indicating whether a suggestion can be added several times
* @param allowEmpty A boolean indicating whether an empty suggestion should be added
* @param choices An array of available choices
* @param emptyText The text to use for the empty suggestion. Defaults to an empty string
Expand All @@ -24,6 +25,7 @@ import { useTranslate } from '../i18n';
* - getSuggestions: A function taking a filter value (string) and returning the matching suggestions
*/
const useSuggestions = ({
allowDuplicates,
allowEmpty,
choices,
emptyText = '',
Expand All @@ -45,6 +47,7 @@ const useSuggestions = ({

const getSuggestions = useCallback(
getSuggestionsFactory({
allowDuplicates,
allowEmpty,
choices,
emptyText: translate(emptyText, { _: emptyText }),
Expand All @@ -59,6 +62,7 @@ const useSuggestions = ({
suggestionLimit,
}),
[
allowDuplicates,
allowEmpty,
choices,
emptyText,
Expand Down Expand Up @@ -89,6 +93,7 @@ const escapeRegExp = value =>

interface Options extends UseChoicesOptions {
choices: any[];
allowDuplicates?: boolean;
allowEmpty?: boolean;
emptyText?: string;
emptyValue?: any;
Expand Down Expand Up @@ -119,7 +124,7 @@ const defaultMatchSuggestion = getChoiceText => (filter, suggestion) => {
* Get the suggestions to display after applying a fuzzy search on the available choices
*
* @example
*
*
* getSuggestions({
* choices: [{ id: 1, name: 'admin' }, { id: 2, name: 'publisher' }],
* optionText: 'name',
Expand All @@ -129,17 +134,17 @@ const defaultMatchSuggestion = getChoiceText => (filter, suggestion) => {
*
* // Will return [{ id: 2, name: 'publisher' }]
* getSuggestions({
* choices: [{ id: 1, name: 'admin' }, { id: 2, name: 'publisher' }],
* optionText: 'name',
* optionValue: 'id',
* getSuggestionText: choice => choice[optionText],
* })('pub')
*
* // Will return [{ id: 2, name: 'publisher' }]
* choices: [{ id: 1, name: 'admin' }, { id: 2, name: 'publisher' }],
* optionText: 'name',
* optionValue: 'id',
* getSuggestionText: choice => choice[optionText],
* })('pub')
*
* // Will return [{ id: 2, name: 'publisher' }]
*/
export const getSuggestionsFactory = ({
choices = [],
allowDuplicates,
allowEmpty,
emptyText,
emptyValue,
Expand Down Expand Up @@ -169,15 +174,15 @@ export const getSuggestionsFactory = ({
// ignore the filter to show more choices
suggestions = removeAlreadySelectedSuggestions(
choices,
selectedItem,
allowDuplicates ? null : selectedItem,
getChoiceValue
);
}
} else {
suggestions = choices.filter(choice => matchSuggestion(filter, choice));
suggestions = removeAlreadySelectedSuggestions(
suggestions,
selectedItem,
allowDuplicates ? null : selectedItem,
getChoiceValue
);
}
Expand Down
11 changes: 7 additions & 4 deletions packages/ra-ui-materialui/src/input/AutocompleteArrayInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ interface Options {
const AutocompleteArrayInput: FunctionComponent<
InputProps<TextFieldProps & Options> & DownshiftProps<any>
> = ({
allowDuplicates,
allowEmpty,
classes: classesOverride,
choices = [],
Expand Down Expand Up @@ -178,6 +179,7 @@ const AutocompleteArrayInput: FunctionComponent<
);

const { getChoiceText, getChoiceValue, getSuggestions } = useSuggestions({
allowDuplicates,
allowEmpty,
choices,
emptyText,
Expand Down Expand Up @@ -234,13 +236,14 @@ const AutocompleteArrayInput: FunctionComponent<

const handleChange = useCallback(
(item: any) => {
let newSelectedItems = selectedItems.includes(item)
? [...selectedItems]
: [...selectedItems, item];
let newSelectedItems =
!allowDuplicates && selectedItems.includes(item)
? [...selectedItems]
: [...selectedItems, item];
setFilterValue('');
input.onChange(newSelectedItems.map(getChoiceValue));
},
[getChoiceValue, input, selectedItems, setFilterValue]
[allowDuplicates, getChoiceValue, input, selectedItems, setFilterValue]
);

const handleDelete = useCallback(
Expand Down

0 comments on commit d5da818

Please sign in to comment.