diff --git a/packages/grafana-ui/src/components/Combobox/Combobox.test.tsx b/packages/grafana-ui/src/components/Combobox/Combobox.test.tsx
index e99a2568faa..6127c007e56 100644
--- a/packages/grafana-ui/src/components/Combobox/Combobox.test.tsx
+++ b/packages/grafana-ui/src/components/Combobox/Combobox.test.tsx
@@ -243,7 +243,19 @@ describe('Combobox', () => {
await userEvent.keyboard('{Enter}');
expect(screen.getByDisplayValue('Use custom value')).toBeInTheDocument();
- expect(onChangeHandler).toHaveBeenCalledWith(expect.objectContaining({ value: 'Use custom value' }));
+ expect(onChangeHandler).toHaveBeenCalledWith(expect.objectContaining({ description: 'Use custom value' }));
+ });
+
+ it('should not allow creating a custom value when it is an existing value', async () => {
+ const onChangeHandler = jest.fn();
+ render();
+ const input = screen.getByRole('combobox');
+ await userEvent.type(input, '4');
+ await userEvent.keyboard('{Enter}');
+ expect(screen.queryByDisplayValue('Use custom value')).not.toBeInTheDocument();
+ expect(screen.getByDisplayValue('Option 4')).toBeInTheDocument();
+ expect(onChangeHandler).toHaveBeenCalledWith(expect.objectContaining({ value: '4' }));
+ expect(onChangeHandler).not.toHaveBeenCalledWith(expect.objectContaining({ description: 'Use custom value' }));
});
it('should provide custom string when all options are numbers', async () => {
diff --git a/packages/grafana-ui/src/components/Combobox/Combobox.tsx b/packages/grafana-ui/src/components/Combobox/Combobox.tsx
index 4c2f6a97b63..471bb22fe5d 100644
--- a/packages/grafana-ui/src/components/Combobox/Combobox.tsx
+++ b/packages/grafana-ui/src/components/Combobox/Combobox.tsx
@@ -129,9 +129,9 @@ export const Combobox = (props: ComboboxProps) =>
let itemsToSet = items;
logOptions(itemsToSet.length, RECOMMENDED_ITEMS_AMOUNT, id, ariaLabelledBy);
if (inputValue && createCustomValue) {
- const optionMatchingInput = items.find(
- (opt) => opt.label === 'Custom value: ' + inputValue || opt.value === inputValue
- );
+ //Since the label of a normal option does not have to match its value and a custom option has the same value and label,
+ //we just focus on the value to check if the option already exists
+ const optionMatchingInput = items.find((opt) => opt.value === inputValue);
if (!optionMatchingInput) {
const customValueOption = {
diff --git a/packages/grafana-ui/src/components/Combobox/useOptions.ts b/packages/grafana-ui/src/components/Combobox/useOptions.ts
index a66e60a2747..b76339cf54e 100644
--- a/packages/grafana-ui/src/components/Combobox/useOptions.ts
+++ b/packages/grafana-ui/src/components/Combobox/useOptions.ts
@@ -62,6 +62,8 @@ export function useOptions(rawOptions: AsyncOptions>) => {
let currentOptions: Array> = opts;
if (createCustomValue && userTypedSearch) {
+ //Since the label of a normal option does not have to match its value and a custom option has the same value and label,
+ //we just focus on the value to check if the option already exists
const customValueExists = opts.some((opt) => opt.value === userTypedSearch);
if (!customValueExists) {
currentOptions = [