Skip to content

useSupportCreateSuggestion

This hook provides support for creating new suggestions in choice-based inputs like autocomplete components. It allows users to create new options when the desired choice doesn’t exist in the available options, either through an onCreate callback or by rendering a creation form.

import { useSupportCreateSuggestion } from 'ra-core';
const {
createId,
createHintId,
getCreateItem,
handleChange,
createElement,
getOptionDisabled,
} = useSupportCreateSuggestion({
filter: searchValue,
handleChange: (eventOrValue) => {
// update your input value
setValue(eventOrValue?.target?.value ?? eventOrValue?.id);
},
onCreate: async (filter) => {
// create a new option and return it
return await createNewOption(filter);
},
});

The hook accepts a configuration object and returns utilities for handling suggestion creation in choice inputs.

PropRequiredTypeDefaultDescription
createNoReactElement-React element rendered when users choose to create a new choice
createLabelNoReactNode'ra.action.create'Label for the create choice item
createItemLabelNostring | ((filter: string) => ReactNode)-Dynamic label that receives the filter value as parameter
createValueNostring'@@ra-create'Value for the create choice item
createHintValueNostring'@@ra-create-hint'Value for the disabled hint item
filterNostring-Current filter/search value entered by the user
handleChangeYes(value: any) => void-Function to call when the input value changes
onCreateNo(filter?: string) => any | Promise<any>-Function called when creating a new option (if create element not provided)
optionTextNoOptionText'name'Property name for the option text

The hook returns an object with:

  • createId: The ID value for the create option
  • createHintId: The ID value for the create hint (disabled) option
  • getCreateItem: Function that returns the create option object
  • handleChange: Enhanced change handler that intercepts create actions
  • createElement: React element to render for creation form (null when not creating)
  • getOptionDisabled: Function to determine if an option should be disabled (i.e. if it’s a hint)
import { useSupportCreateSuggestion } from 'ra-core';
import { useState } from 'react';
const AuthorInput = () => {
const [value, setValue] = useState('');
const [filter, setFilter] = useState('');
const {
getCreateItem,
handleChange,
getOptionDisabled,
} = useSupportCreateSuggestion({
filter,
handleChange: (eventOrValue) => {
setValue(eventOrValue?.target?.value ?? eventOrValue?.id);
},
onCreate: async (authorName) => {
// Call your API to create a new author
return await createNewAuthor(authorName);
},
createItemLabel: 'Create author "%{item}"',
});
const createItem = getCreateItem(filter);
const options = [
...existingAuthors,
createItem,
];
return (
<div>
<input
type="text"
placeholder="Search authors..."
value={filter}
onChange={(e) => setFilter(e.target.value)}
/>
<select value={value} onChange={handleChange}>
{options.map(option => (
<option
key={option.id}
value={option.id}
disabled={getOptionDisabled(option)}
>
{option.name}
</option>
))}
</select>
</div>
);
};

When you need more control over the creation process, you can provide a React element to be rendered for creating new options.

This form component can use useCreateSuggestionContext to access:

  • filter: The search filter that triggered the creation
  • onCancel: Function to cancel the creation and hide the form
  • onCreate: Function to call when creation succeeds, passing the new item
import {
useSupportCreateSuggestion,
useCreateSuggestionContext,
CreateBase
} from 'ra-core';
const CreateAuthorForm = () => {
const { filter, onCancel, onCreate } = useCreateSuggestionContext();
return (
<CreateBase
resource="authors"
redirect={false}
mutationOptions={{
onSuccess: onCreate,
}}
>
<SimpleForm defaultValues={{ name: filter }}>
<TextInput source="name" />
<TextInput source="email" />
<button type="button" onClick={onCancel}>
Cancel
</button>
</SimpleForm>
</CreateBase>
);
};
const AuthorInput = () => {
const [value, setValue] = useState('');
const [filter, setFilter] = useState('');
const {
getCreateItem,
handleChange,
createElement,
getOptionDisabled,
} = useSupportCreateSuggestion({
filter,
handleChange: (eventOrValue) => {
setValue(eventOrValue?.target?.value ?? eventOrValue?.id);
},
create: <CreateAuthorForm />,
createItemLabel: 'Create author "%{item}"',
});
const createItem = getCreateItem(filter);
const options = [
...existingAuthors,
createItem,
];
return (
<div>
<input
type="text"
placeholder="Search authors..."
value={filter}
onChange={(e) => setFilter(e.target.value)}
/>
<select value={value} onChange={handleChange}>
{options.map(option => (
<option
key={option.id}
value={option.id}
disabled={getOptionDisabled(option)}
>
{option.name}
</option>
))}
</select>
{createElement}
</div>
);
};

Provides a React element that will be rendered when users choose to create a new option. When this prop is provided, the hook will render the element instead of calling onCreate. The element should use useCreateSuggestionContext to access the filter value and callback functions.

const CreateForm = () => {
const { filter, onCancel, onCreate } = useCreateSuggestionContext();
const handleSubmit = async (data) => {
try {
const newItem = await createItem(data);
onCreate(newItem); // This will select the new item and close the form
} catch (error) {
// Handle error
}
};
return (
<form onSubmit={handleSubmit}>
<input defaultValue={filter} name="name" />
<button type="submit">Create</button>
<button type="button" onClick={onCancel}>
Cancel
</button>
</form>
);
};
useSupportCreateSuggestion({
create: <CreateForm />
});

Sets the label for the create option. Can be a string, translation key, or any React node.

useSupportCreateSuggestion({
createLabel: 'Add new item'
});

Provides a dynamic label that receives the filter value as a parameter. When provided, this creates two different behaviors:

  • With no filter: Shows a disabled hint option (using the createLabel text)
  • With filter: Shows an active create option with the filter value (using createItemLabel)

This provides better UX by guiding users on how to create new options.

useSupportCreateSuggestion({
createItemLabel: 'Create category "%{item}"',
// When filter is "Sports", shows: "Create category 'Sports'"
});
// Or as a function:
useSupportCreateSuggestion({
createItemLabel: (filter) => `Add "${filter}" as new category`
});

Customizes the value used internally to identify the create option. This is useful if the default value conflicts with your data.

useSupportCreateSuggestion({
createValue: '@@my-create-id'
});

Customizes the value used for the disabled hint option when createItemLabel is provided and no filter is set.

useSupportCreateSuggestion({
createHintValue: '@@my-hint-id'
});

The current search/filter value entered by the user. This value is used to populate the create option label and is passed to the onCreate callback or the create element context.

const [searchValue, setSearchValue] = useState('');
useSupportCreateSuggestion({
filter: searchValue
});

The function to call when the input value changes. The hook will intercept changes that match the create value and handle them specially, otherwise it will call this function with the original event or value.

useSupportCreateSuggestion({
handleChange: (eventOrValue) => {
setValue(eventOrValue?.target?.value ?? eventOrValue?.id);
}
});

A function called when creating a new option, if the create element is not provided. Should return the newly created item.

useSupportCreateSuggestion({
onCreate: async (filterValue) => {
// create a new option and return it
return await createNewOption(filterValue);
}
});

Specifies which property of the option objects contains the display text. If your options use a different property than name, specify it here.

useSupportCreateSuggestion({
optionText: 'title', // Uses 'title' instead of 'name'
});
// Also accepts function for more complex scenarios
useSupportCreateSuggestion({
optionText: (option) => `${option.firstName} ${option.lastName}`
});