mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Grafana-UI: Allow <Select /> value to be unset (#32136)
* Fix: Allow <Select /> value to be unset * clean up * fix null object in select onChange * Revert "fix null object in select onChange" This reverts commit 4b157073884938e5e6a1fac1bbafa7c6017cb361. * undo onChange arg type change * fix tests
This commit is contained in:
parent
4a2ba2a3ab
commit
7389b2ecac
@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
import { mount, ReactWrapper } from 'enzyme';
|
import { mount, ReactWrapper } from 'enzyme';
|
||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import userEvent from '@testing-library/user-event';
|
||||||
import selectEvent from 'react-select-event';
|
import selectEvent from 'react-select-event';
|
||||||
import { SelectBase } from './SelectBase';
|
import { SelectBase } from './SelectBase';
|
||||||
import { SelectableValue } from '@grafana/data';
|
import { SelectableValue } from '@grafana/data';
|
||||||
@ -43,6 +44,25 @@ describe('SelectBase', () => {
|
|||||||
expect(screen.getByLabelText('My select')).toBeInTheDocument();
|
expect(screen.getByLabelText('My select')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('allows the value to be unset', async () => {
|
||||||
|
const Test = () => {
|
||||||
|
const option = { value: 'test-value', label: 'Test label' };
|
||||||
|
const [value, setValue] = useState<SelectableValue<string> | null>(option);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<button onClick={() => setValue(null)}>clear value</button>
|
||||||
|
<SelectBase value={value} onChange={setValue} options={[option]} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
render(<Test />);
|
||||||
|
expect(screen.queryByText('Test label')).toBeInTheDocument();
|
||||||
|
userEvent.click(screen.getByText('clear value'));
|
||||||
|
expect(screen.queryByText('Test label')).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
describe('when openMenuOnFocus prop', () => {
|
describe('when openMenuOnFocus prop', () => {
|
||||||
describe('is provided', () => {
|
describe('is provided', () => {
|
||||||
it('opens on focus', () => {
|
it('opens on focus', () => {
|
||||||
|
@ -60,7 +60,7 @@ export interface SelectCommonProps<T> {
|
|||||||
/** Use a custom element to control Select. A proper ref to the renderControl is needed if 'portal' isn't set to null*/
|
/** Use a custom element to control Select. A proper ref to the renderControl is needed if 'portal' isn't set to null*/
|
||||||
renderControl?: ControlComponent<T>;
|
renderControl?: ControlComponent<T>;
|
||||||
tabSelectsValue?: boolean;
|
tabSelectsValue?: boolean;
|
||||||
value?: SelectValue<T>;
|
value?: SelectValue<T> | null;
|
||||||
/** Sets the width to a multiple of 8px. Should only be used with inline forms. Setting width of the container is preferred in other cases.*/
|
/** Sets the width to a multiple of 8px. Should only be used with inline forms. Setting width of the container is preferred in other cases.*/
|
||||||
width?: number;
|
width?: number;
|
||||||
isOptionDisabled?: () => boolean;
|
isOptionDisabled?: () => boolean;
|
||||||
|
@ -74,10 +74,14 @@ describe('Select utils', () => {
|
|||||||
expect(cleanValue('test1', optGroup)).toEqual([{ label: 'Group 4 - Option 1', value: 'test1' }]);
|
expect(cleanValue('test1', optGroup)).toEqual([{ label: 'Group 4 - Option 1', value: 'test1' }]);
|
||||||
expect(cleanValue(3, options)).toEqual([{ label: 'Option 3', value: 3 }]);
|
expect(cleanValue(3, options)).toEqual([{ label: 'Option 3', value: 3 }]);
|
||||||
});
|
});
|
||||||
it('should return undefined for null/undefined/empty values', () => {
|
|
||||||
|
it('should return null for null values', () => {
|
||||||
|
expect(cleanValue(null, options)).toEqual([null]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return undefined for undefined/empty values', () => {
|
||||||
expect(cleanValue([undefined], options)).toEqual(undefined);
|
expect(cleanValue([undefined], options)).toEqual(undefined);
|
||||||
expect(cleanValue(undefined, options)).toEqual(undefined);
|
expect(cleanValue(undefined, options)).toEqual(undefined);
|
||||||
expect(cleanValue(null, options)).toEqual(undefined);
|
|
||||||
expect(cleanValue('', options)).toEqual(undefined);
|
expect(cleanValue('', options)).toEqual(undefined);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -9,7 +9,8 @@ export const cleanValue = (value: any, options: Array<SelectableValue | Selectab
|
|||||||
const filtered = value.filter(Boolean);
|
const filtered = value.filter(Boolean);
|
||||||
return filtered?.length ? filtered : undefined;
|
return filtered?.length ? filtered : undefined;
|
||||||
}
|
}
|
||||||
if (typeof value === 'object' && value !== null) {
|
if (typeof value === 'object') {
|
||||||
|
// we want to allow null through into here, so the Select value can be unset
|
||||||
return [value];
|
return [value];
|
||||||
}
|
}
|
||||||
if (typeof value === 'string' || typeof value === 'number') {
|
if (typeof value === 'string' || typeof value === 'number') {
|
||||||
|
Loading…
Reference in New Issue
Block a user