Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 47 additions & 20 deletions packages/ra-ui-materialui/src/input/SelectArrayInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
styled,
useThemeProps,
} from '@mui/material/styles';
import { useCallback, useRef, type ChangeEvent } from 'react';
import { useCallback, useRef, type ReactNode, type ChangeEvent } from 'react';
import clsx from 'clsx';
import {
Select,
Expand All @@ -28,6 +28,7 @@
useGetRecordRepresentation,
type SupportCreateSuggestionOptions,
useSupportCreateSuggestion,
useTranslate,
} from 'ra-core';
import { InputHelperText } from './InputHelperText';

Expand Down Expand Up @@ -89,6 +90,14 @@
* { id: 'lifestyle', name: 'myroot.tags.lifestyle' },
* { id: 'photography', name: 'myroot.tags.photography' },
* ];
*
* You can also specify a text to display when no value is selected using the `emptyText` prop.
* @example
* const choices = [
* { id: 'email', name: 'Email' },
* { id: 'push', name: 'Push Notification' },
* ];
* <SelectArrayInput source="channels" choices={choices} emptyText={<i>All Channels</i>} />
*/
export const SelectArrayInput = (inProps: SelectArrayInputProps) => {
const props = useThemeProps({
Expand All @@ -102,6 +111,7 @@
createLabel,
createValue,
disableValue = 'disabled',
emptyText = '',
format,
helperText,
label,
Expand Down Expand Up @@ -130,6 +140,8 @@

const inputLabel = useRef(null);

const translate = useTranslate();

const {
allChoices,
isPending,
Expand Down Expand Up @@ -295,6 +307,15 @@
: {};
const renderHelperText = !!fetchError || helperText !== false || invalid;

const renderEmptyValue = useCallback(() => {

Check failure on line 310 in packages/ra-ui-materialui/src/input/SelectArrayInput.tsx

View workflow job for this annotation

GitHub Actions / typecheck

React Hook "useCallback" is called conditionally. React Hooks must be called in the exact same order in every component render. Did you accidentally call a React Hook after an early return?
if (typeof emptyText === 'string' && emptyText === '') {
return null;
}
return typeof emptyText === 'string'
? translate(emptyText, { _: emptyText })
: emptyText;
}, [emptyText, translate]);

return (
<>
<StyledFormControl
Expand Down Expand Up @@ -330,26 +351,31 @@
}
multiple
error={!!fetchError || invalid}
renderValue={(selected: any[]) => (
<div className={SelectArrayInputClasses.chips}>
{(Array.isArray(selected) ? selected : [])
.map(item =>
(allChoices || []).find(
// eslint-disable-next-line eqeqeq
choice => getChoiceValue(choice) == item
renderValue={(selected: any[]) => {
if (!selected || selected.length === 0) {
return renderEmptyValue();
}
return (
<div className={SelectArrayInputClasses.chips}>
{(Array.isArray(selected) ? selected : [])
.map(item =>
(allChoices || []).find(
// eslint-disable-next-line eqeqeq
choice => getChoiceValue(choice) == item

Check failure on line 364 in packages/ra-ui-materialui/src/input/SelectArrayInput.tsx

View workflow job for this annotation

GitHub Actions / typecheck

Insert `⏎···············································`
)
)
)
.filter(item => !!item)
.map(item => (
<Chip
key={getChoiceValue(item)}
label={renderMenuItemOption(item)}
className={SelectArrayInputClasses.chip}
size="small"
/>
))}
</div>
)}
.filter(item => !!item)
.map(item => (
<Chip
key={getChoiceValue(item)}
label={renderMenuItemOption(item)}
className={SelectArrayInputClasses.chip}

Check failure on line 372 in packages/ra-ui-materialui/src/input/SelectArrayInput.tsx

View workflow job for this annotation

GitHub Actions / typecheck

Replace `SelectArrayInputClasses.chip` with `⏎················································SelectArrayInputClasses.chip⏎············································`
size="small"
/>
))}
</div>
);
}}
disabled={disabled || readOnly}
readOnly={readOnly}
data-testid="selectArray"
Expand Down Expand Up @@ -383,6 +409,7 @@
options?: SelectProps;
InputLabelProps?: Omit<InputLabelProps, 'htmlFor' | 'id' | 'ref'>;
source?: string;
emptyText?: ReactNode;
onChange?: (event: ChangeEvent<HTMLInputElement> | RaRecord) => void;
};

Expand Down
Loading