mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Cascader: Add enable custom value (#21812)
* Add an early exit * Fix issue with blur and only display label * Remove unused code * Enabled custom value * Update test * Add custom value creating according to #21869
This commit is contained in:
parent
3617e59548
commit
20c4d00df8
@ -47,3 +47,7 @@ export const simple = () => (
|
|||||||
export const withInitialValue = () => (
|
export const withInitialValue = () => (
|
||||||
<Cascader options={options} initialValue="3" onSelect={val => console.log(val)} />
|
<Cascader options={options} initialValue="3" onSelect={val => console.log(val)} />
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const withCustomValue = () => (
|
||||||
|
<Cascader options={options} allowCustomValue initialValue="Custom Initial Value" onSelect={val => console.log(val)} />
|
||||||
|
);
|
||||||
|
@ -29,18 +29,22 @@ const options = [
|
|||||||
|
|
||||||
const flatOptions = [
|
const flatOptions = [
|
||||||
{
|
{
|
||||||
|
singleLabel: 'Second',
|
||||||
label: 'First / Second',
|
label: 'First / Second',
|
||||||
value: ['1', '2'],
|
value: ['1', '2'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
singleLabel: 'Third',
|
||||||
label: 'First / Third',
|
label: 'First / Third',
|
||||||
value: ['1', '3'],
|
value: ['1', '3'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
singleLabel: 'Fourth',
|
||||||
label: 'First / Fourth',
|
label: 'First / Fourth',
|
||||||
value: ['1', '4'],
|
value: ['1', '4'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
singleLabel: 'FirstFirst',
|
||||||
label: 'FirstFirst',
|
label: 'FirstFirst',
|
||||||
value: ['5'],
|
value: ['5'],
|
||||||
},
|
},
|
||||||
|
@ -15,6 +15,7 @@ interface CascaderProps {
|
|||||||
onSelect(val: string): void;
|
onSelect(val: string): void;
|
||||||
size?: FormInputSize;
|
size?: FormInputSize;
|
||||||
initialValue?: string;
|
initialValue?: string;
|
||||||
|
allowCustomValue?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CascaderState {
|
interface CascaderState {
|
||||||
@ -64,6 +65,7 @@ export class Cascader extends React.PureComponent<CascaderProps, CascaderState>
|
|||||||
cpy.push(option);
|
cpy.push(option);
|
||||||
if (!option.items) {
|
if (!option.items) {
|
||||||
selectOptions.push({
|
selectOptions.push({
|
||||||
|
singleLabel: cpy[cpy.length - 1].label,
|
||||||
label: cpy.map(o => o.label).join(this.props.separator || ' / '),
|
label: cpy.map(o => o.label).join(this.props.separator || ' / '),
|
||||||
value: cpy.map(o => o.value),
|
value: cpy.map(o => o.value),
|
||||||
});
|
});
|
||||||
@ -84,10 +86,13 @@ export class Cascader extends React.PureComponent<CascaderProps, CascaderState>
|
|||||||
if (optionPath.indexOf(initValue) === optionPath.length - 1) {
|
if (optionPath.indexOf(initValue) === optionPath.length - 1) {
|
||||||
return {
|
return {
|
||||||
rcValue: optionPath,
|
rcValue: optionPath,
|
||||||
activeLabel: option.label || '',
|
activeLabel: option.singleLabel || '',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (this.props.allowCustomValue) {
|
||||||
|
return { rcValue: [], activeLabel: initValue };
|
||||||
|
}
|
||||||
return { rcValue: [], activeLabel: '' };
|
return { rcValue: [], activeLabel: '' };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +100,7 @@ export class Cascader extends React.PureComponent<CascaderProps, CascaderState>
|
|||||||
onChange = (value: string[], selectedOptions: CascaderOption[]) => {
|
onChange = (value: string[], selectedOptions: CascaderOption[]) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
rcValue: value,
|
rcValue: value,
|
||||||
activeLabel: selectedOptions.map(o => o.label).join(this.props.separator || ' / '),
|
activeLabel: selectedOptions[selectedOptions.length - 1].label,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.props.onSelect(selectedOptions[selectedOptions.length - 1].value);
|
this.props.onSelect(selectedOptions[selectedOptions.length - 1].value);
|
||||||
@ -103,12 +108,22 @@ export class Cascader extends React.PureComponent<CascaderProps, CascaderState>
|
|||||||
|
|
||||||
//For select
|
//For select
|
||||||
onSelect = (obj: SelectableValue<string[]>) => {
|
onSelect = (obj: SelectableValue<string[]>) => {
|
||||||
|
const valueArray = obj.value || [];
|
||||||
this.setState({
|
this.setState({
|
||||||
activeLabel: obj.label || '',
|
activeLabel: obj.singleLabel || '',
|
||||||
rcValue: obj.value || [],
|
rcValue: valueArray,
|
||||||
isSearching: false,
|
isSearching: false,
|
||||||
});
|
});
|
||||||
this.props.onSelect(this.state.rcValue[this.state.rcValue.length - 1]);
|
this.props.onSelect(valueArray[valueArray.length - 1]);
|
||||||
|
};
|
||||||
|
|
||||||
|
onCreateOption = (value: string) => {
|
||||||
|
this.setState({
|
||||||
|
activeLabel: value,
|
||||||
|
rcValue: [],
|
||||||
|
isSearching: false,
|
||||||
|
});
|
||||||
|
this.props.onSelect(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
onClick = () => {
|
onClick = () => {
|
||||||
@ -138,47 +153,36 @@ export class Cascader extends React.PureComponent<CascaderProps, CascaderState>
|
|||||||
|
|
||||||
onInputKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
onInputKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||||
if (
|
if (
|
||||||
e.key !== 'ArrowDown' &&
|
e.key === 'ArrowDown' ||
|
||||||
e.key !== 'ArrowUp' &&
|
e.key === 'ArrowUp' ||
|
||||||
e.key !== 'Enter' &&
|
e.key === 'Enter' ||
|
||||||
e.key !== 'ArrowLeft' &&
|
e.key === 'ArrowLeft' ||
|
||||||
e.key !== 'ArrowRight'
|
e.key === 'ArrowRight'
|
||||||
) {
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
focusCascade: false,
|
focusCascade: false,
|
||||||
isSearching: true,
|
isSearching: true,
|
||||||
});
|
});
|
||||||
if (e.key === 'Backspace') {
|
|
||||||
const label = this.state.activeLabel || '';
|
|
||||||
this.setState({
|
|
||||||
activeLabel: label.slice(0, -1),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
onInputChange = (value: string) => {
|
|
||||||
this.setState({
|
|
||||||
activeLabel: value,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { size } = this.props;
|
const { size, allowCustomValue } = this.props;
|
||||||
const { focusCascade, isSearching, searchableOptions, rcValue, activeLabel } = this.state;
|
const { focusCascade, isSearching, searchableOptions, rcValue, activeLabel } = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{isSearching ? (
|
{isSearching ? (
|
||||||
<Select
|
<Select
|
||||||
inputValue={activeLabel}
|
allowCustomValue={allowCustomValue}
|
||||||
placeholder="Search"
|
placeholder="Search"
|
||||||
autoFocus={!focusCascade}
|
autoFocus={!focusCascade}
|
||||||
onChange={this.onSelect}
|
onChange={this.onSelect}
|
||||||
onInputChange={this.onInputChange}
|
|
||||||
onBlur={this.onBlur}
|
onBlur={this.onBlur}
|
||||||
options={searchableOptions}
|
options={searchableOptions}
|
||||||
size={size || 'md'}
|
size={size || 'md'}
|
||||||
|
onCreateOption={this.onCreateOption}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<RCCascader
|
<RCCascader
|
||||||
|
Loading…
Reference in New Issue
Block a user