Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix createLabel option should not be clickable for <AutocompleteInput> and <AutocompleteArrayInput> #10321

Merged
merged 9 commits into from
Nov 8, 2024

Conversation

slax57
Copy link
Contributor

@slax57 slax57 commented Oct 31, 2024

Problem

The documentation encourages to use values like the following for createLabel:

<AutocompleteInput
    source="author"
    choices={authors}
    onCreate={onCreate}
    createLabel="Start typing to create a new item"
/>

One would expect this label to be only a hint, but this createLabel option is actually clickable, and what's more, it pre-selects "Start typing to create a new item" as value.

It would seem more logical to disable this option, to prevent the bug and make it clear that it's just a hint.

Solution

Upon further analysis, having a clickable createLabel option actually makes sense for components that do not allow to type a value in, like <SelectInput> and <SelectArrayInput>.

But for components like <AutocompleteInput> and <AutocompleteArrayInput>, we cannot know of the createLabel option is supposed to be clickable or not, because it depends on the intent conveyed by the actual chosen label (createLabel="Start typing to create a new item" should not be clickable, but createLabel="Click to create a new item" should be).

Since the <AutocompleteInput> and <AutocompleteArrayInput> also support a createItemLabel option, we decided that this would be the only way to start the creation workflow for these components, and hence the createLabel option will always be considered as a hint (and be disabled).

TLDR: Components supporting both createItemLabel and createLabel will consider createLabel as a hint (option will be disabled), while components supporting only createLabel will consider this option clickable.

Todo

  • Update useSupportCreateSuggestion to work as described
  • Add stories
  • Add tests
  • Update documentation

How To Test

  • Storybooks
    • AutocompleteArrayInput
    • AutocompleteInput
    • SelectArrayInput
    • SelectInput
  • Run the unit tests

Additional Checks

  • The PR targets master for a bugfix, or next for a feature
  • The PR includes unit tests (if not possible, describe why)
  • The PR includes one or several stories (if not possible, describe why)
  • The documentation is up to date

Also, please make sure to read the contributing guidelines.

@slax57 slax57 added the WIP Work In Progress label Oct 31, 2024
Comment on lines 507 to 529
const NoCreateItemLabelInput = () => {
const [choices, setChoices] = useState(choicesForCreationSupport);
return (
<AutocompleteInput
source="author"
choices={choices}
onCreate={async filter => {
if (!filter) return;

const newOption = {
id: choices.length + 1,
name: filter,
};
setChoices(options => [...options, newOption]);
// Wait until next tick to give some time for React to update the state
await new Promise(resolve => setTimeout(resolve));
return newOption;
}}
createItemLabel="" // TODO - FIX THIS
createLabel="Click to create a new item"
/>
);
};
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this use case would be nice for people still wanting to start the creation workflow with the createLabel and not the createItemLabel. All they would need to do would be to pass createItemLabel="".
So I'll see if I can make it work (as it currently doesn't).

Comment on lines +539 to +543
} else if (
inputValue &&
filterValue &&
!doesQueryMatchSuggestion(filterValue)
) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually not directly linked to the main fix, but fixes an issue where <AutocompleteArrayInput> would still render the 'Create' option when the filter is empty (i.e. the createLabel option), although this should no longer be the case according to this PR.

*/
export const useSupportCreateSuggestion = (
options: SupportCreateSuggestionOptions
): UseSupportCreateValue => {
const {
create,
createLabel = 'ra.action.create',
createItemLabel = 'ra.action.create_item',
createItemLabel,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One could argue this is technically a BC, but I thought it was worth it to reuse the createItemLabel prop to decide whether or not to make the createLabel option clickable, rather than introducing yet another prop.
Besides, this hook can probably be considered an internal hook, as it is not documented.

@@ -905,7 +951,7 @@ describe('<AutocompleteArrayInput />', () => {
selector: 'input',
})
);
expect(screen.queryAllByRole('option')).toHaveLength(3);
expect(screen.queryAllByRole('option')).toHaveLength(2);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is because we no longer display the 'Create' item when the input is empty.

@slax57 slax57 added RFR Ready For Review and removed WIP Work In Progress labels Nov 8, 2024
Copy link
Collaborator

@djhi djhi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent!

@@ -223,6 +223,21 @@ If you just need to ask users for a single string to create the new option, you

If you're in a `<ReferenceArrayInput>` or `<ReferenceManyToManyInput>`, the `handleSubmit` will need to create a new record in the related resource. Check the [Creating New Choices](#creating-new-choices) for an example.

## `createLabel`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@djhi djhi merged commit c795bf2 into master Nov 8, 2024
2 checks passed
@djhi djhi deleted the Autocomplete-createLabel-disabled branch November 8, 2024 14:16
@djhi djhi added this to the 5.3.3 milestone Nov 8, 2024
| `createLabel` | Optional | `string` | `ra.action. create` | The label for the menu item allowing users to create a new choice. Used when the filter is empty |
| `createItemLabel` | Optional | `string` | `ra.action .create_item` | The label for the menu item allowing users to create a new choice. Used when the filter is not empty |
| `createLabel` | Optional | `string` | - | The label used as hint to let users know they can create a new choice. Displayed when the filter is empty. |
| `createItemLabel` | Optional | `string` | `ra.action .create_item` | The label for the menu item allowing users to create a new choice. Used when the filter is not empty. |
| `debounce` | Optional | `number` | `250` | The delay to wait before calling the setFilter function injected when used in a ReferenceArray Input. |
| `emptyValue` | Optional | `any` | `''` | The value to use for the empty element |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
| `emptyValue` | Optional | `any` | `''` | The value to use for the empty element |
| `emptyValue` | Optional | `any` | `''` | The value to use for the empty element. |

@@ -60,8 +60,8 @@ The form value for the source must be an array of the selected values, e.g.
|----------------------------|----------|-----------------------|--------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `choices` | Required | `Object[]` | - | List of choices |
| `create` | Optional | `Element` | `-` | A React Element to render when users want to create a new choice |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
| `create` | Optional | `Element` | `-` | A React Element to render when users want to create a new choice |
| `create` | Optional | `Element` | `-` | A React Element to render when users want to create a new choice. |

| `createLabel` | Optional | `string` | `ra.action. create` | The label for the menu item allowing users to create a new choice. Used when the filter is empty |
| `createItemLabel` | Optional | `string` | `ra.action .create_item` | The label for the menu item allowing users to create a new choice. Used when the filter is not empty |
| `createLabel` | Optional | `string` | - | The label used as hint to let users know they can create a new choice. Displayed when the filter is empty. |
| `createItemLabel` | Optional | `string` | `ra.action .create_item` | The label for the menu item allowing users to create a new choice. Used when the filter is not empty. |
| `debounce` | Optional | `number` | `250` | The delay to wait before calling the setFilter function injected when used in a ReferenceArray Input. |
| `emptyValue` | Optional | `any` | `''` | The value to use for the empty element |
| `filterToQuery` | Optional | `string` => `Object` | `q => ({ q })` | How to transform the searchText into a parameter for the data provider |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
| `filterToQuery` | Optional | `string` => `Object` | `q => ({ q })` | How to transform the searchText into a parameter for the data provider |
| `filterToQuery` | Optional | `string` => `Object` | `q => ({ q })` | How to transform the searchText into a parameter for the data provider. |

same for the following props (but GH doesn't allow me to add suggestions there)

/>
```

## `createItemLabel`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: Could you please add a screenshot

Suggested change
## `createItemLabel`
![Create Label](./img/AutocompleteArrayInput-createLabel.png)
## `createItemLabel`


## `createItemLabel`

If you set the `create` or `onCreate` prop, `<AutocompleteArrayInput>` lets users create new options. When the text entered by the user doesn't match any option, the input renders a "Create XXX" menu item at the bottom of the list.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick (non-blocking):

Suggested change
If you set the `create` or `onCreate` prop, `<AutocompleteArrayInput>` lets users create new options. When the text entered by the user doesn't match any option, the input renders a "Create XXX" menu item at the bottom of the list.
When you set the `create` or `onCreate` prop, `<AutocompleteArrayInput>` lets users create new options. When the text entered by the user doesn't match any option, the input renders a "Create XXX" menu item at the bottom of the list.

| `createLabel` | Optional | `string` | `ra.action .create` | The label for the menu item allowing users to create a new choice. Used when the filter is empty |
| `createItemLabel` | Optional | `string` | `ra.action .create_item` | The label for the menu item allowing users to create a new choice. Used when the filter is not empty |
| `createLabel` | Optional | `string` | - | The label used as hint to let users know they can create a new choice. Displayed when the filter is empty. |
| `createItemLabel` | Optional | `string` | `ra.action .create_item` | The label for the menu item allowing users to create a new choice. Used when the filter is not empty. |
| `debounce` | Optional | `number` | `250` | The delay to wait before calling the setFilter function injected when used in a ReferenceInput. |
| `emptyText` | Optional | `string` | `''` | The text to use for the empty element |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

todo: ‏same here

createItemLabel="Add a new role: %{item}"
/>
```

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: Could you please add a screenshot

Suggested change
![Create Item Label](./img/AutocompleteArrayInput-createItemLabel.png)

createLabel="Add a new role"
/>
```

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: could you add a screenshot here too

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
RFR Ready For Review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants