Hi guys,
1) The question is simple how to set current value of the input? Like when I put focus there and see already written text.
2) Or how to enable editing of the existing tag, that I could click and continue typing?
Thanks.
This is critical for my application. I looked into 2 and couldn't find any options to do this and would greatly appreciate a workaround (couldn't come up with that either).
Is what you both are referring to is the ability to modify an existing selection's text, ie. Say the selected text is "AAAAA" and you want to select "AAAAB" you want to delete the last letter and change it... You can't. You have to delete the whole thing and start again?
If so, then I wholeheartedly agree, this seems like a really silly little bug... @JedWatson any ideas?
@Siyfion yes, correct it is one option and another one is to set current value, thus we could remove element onclick and add set current value with focus, which will end with editing mode.
@JedWatson I also need this for my application. Any ideas how can we implement it ?
This would be great to implement. Does maybe one of the 137 PRs of this writing solve this?
Is it correctly understood that editing a selected value should only be possible if it is a Select.Creatable
?
I have this requirement too when the select is Creatable
Ellipses are displayed on the field for long text but not able to place cursor pointer at the end. Not able to edit.
@JedWatson pushing up this, just noticed that we need the same thing it's opened from February
Looks like this ticket is a dupe of #1868 and the suggested solution is to create your own value and option component which handles the rendering and focus/edit etc. behaviour. I haven't tried myself so would be nice if somebody has a codepen/jsfiddle.
I've just run into the same issue and haven't been able to find a solution yet.
Does anyone know whether there is a workaround?
I'd really appreciate any help since I'd need to get this feature working asap.
Thanks
I see not only me has the same problem! SOLUTION, please come :P
I was not able to resolve it. Had to do some workaround, not even close to the react-select.
Has anyone found a solution for this? The library is great but this feature would _greatly_ improve UX.
Just encountered this problem: I was hoping to replace an editable-text control that I had with react-select, so that text can still be edited, just with a list of suggestions. But I can't, because react-select does not allow editing...
I was not able to resolve it as well.. anyone came up with a solution??
Two years later... Another +1. @JedWatson ?
Another +1. @JedWatson ?
This needs to be added as it is a basic requirement.
With v2.x you can overwrite the internal components of the Select
with the Components Framework to either replace or enhance functionality.
Here is a very basic example of a CreateableSelect
with editable custom option: CodeSandbox.
Easy to implement with the help of the documentation and a look into the core code here on github.
If you are looking for editable option in a simple Select
component, you should think about using unique identifiers for your options to identify them if you change the label (and maybe values).
Another +1, a little shocked this isn't a core feature.
@Rall3n thanks for the info but I'm a little confused by the CodeSandbox.. I want to be able to select an item from the dropdown and then edit it. For example, if I want to select option 'AAAAA', delete the last 'A' and type a 'B' so that the input contains 'AAAAB', I don't have to delete the entire item and start over. I can't seem to make that happen with this example...
@jonnydodad Easy (using my example as reference):
Edit onChange
to not save the value into either value
or createdOption
, but into just value
:
onChange = (option, action) => {
// If you want to keep the option in the menu, make a copy of the option as this is a reference to the element in the options array.
var newOption = Object.assign({}, option);
this.setState({ value: newOption });
}
Remove the __isNew__
check from SingleValue
and always render the input:
SingleValue = ({ children, ...props}) => {
return (<components.SingleValue {...props}>
<input
type="text"
{ ... }
/>
</components.SingleValue>)
};
Update onEditChange
to set state to value
instead of createdOption
:
onEditChange = (e) => {
/* ... */
this.setState({ value: newOption })
}
And for good measure remove the selection of this.state.createdOption
from the value
prop of CreatableSelect
:
<CreatableSelect
{ ... }
value={this.state.value}
/>
And et voil脿: You can now edit every option you have selected.
@Rall3n wow awesome thank you so much!
@jonnydodad I went with a different approach.
I pulled a reference to the internals via ref
<CreatableSelect
ref={ref => {
this.select = ref;
}}
/>
I assigned the input value of the ref manually when the component is focused
handleFocus = element => {
if (this.state.value) {
this.select.state.inputValue = this.state.value.label;
}
};
and then removed focus when the menu becomes closed
handleMenuClose = () => {
this.select.blur();
};
Would be interested in a solution for when isMulti
is enabled. Hitting backspace with the cursors after a selected value should make that value editable instead of outright deleting it.
@inottawa The approach you suggested is working fine if onFocus is triggered on mouse click. If it is happening because of pressing tab key then the behaviour is similar to what we get by default.
Here is the Codesandbox
I still need this but for the AsyncSelect. Setting select.state.value etc doesn't work .. and it seems like the AsyncSelect has a select which has a select which has a select .. really weird structure :smile:
I was struggling to get AsyncCreatableSelect
to be editable. I've downgraded to react-select 2.4.4 because 3.x did not seem to work.
In the example code below, import is not as described in the docs, because I could not fetch react-select/async-creatable
. And import AsyncCreatableSelect from 'react-select'
seems to yield a regular Select
component.
Hope this helps.
'use strict'
import React from 'react'
import { AsyncCreatable } from 'react-select'
export default class MyComponent extends React.Component {
constructor(props) {
super(props)
this.select = null
this.state = {value: null, isLoading: false, menuIsOpen: false}
if (props.value) this.state.value = {label: props.value}
this.setRef = this.setRef.bind(this)
this.loadOptions = this.loadOptions.bind(this)
this.onChange = this.onChange.bind(this)
this.onInputChange = this.onInputChange.bind(this)
this.onFocus = this.onFocus.bind(this)
this.onKeyDown = this.onKeyDown.bind(this)
this.onMenuClose = this.onMenuClose.bind(this)
}
// Set reference to the select element.
// Note the nested `select` objects!
setRef(element) {
this.select = element
? element.select.select.select
: null
}
// Load options and set loading state.
loadOptions(value) {
this.setState({isLoading: true})
return new Promise(resolve => {
setTimeout(() => {
resolve([
{value: "123", label: "Fake data"}
])
this.setState({isLoading: false})
}, 1000)
})
}
// Gets called when an option is chosen or created.
onChange(value) {
this.setState({value: value})
}
// Toggle menu by presence of input.
// Reset value if input is emptied.
onInputChange(value, context) {
this.setState({menuIsOpen: !!value})
if (!value && context.action === "input-change") {
this.onChange(null)
}
}
// Restore input value.
onFocus() {
if (this.state.value) {
this.select.handleInputChange({
currentTarget: {value: this.state.value.label}
})
}
}
// Close menu when pressing enter. Submit does not work on mobile.
onKeyDown(event) {
if (event.keyCode === 13 && !this.state.isLoading) {
this.onMenuClose()
}
}
// Blur select element to trigger onFocus on next click.
onMenuClose() {
this.select.blur()
}
render() {
const { value, menuIsOpen } = this.state
return (
<AsyncCreatable
ref={this.setRef}
value={value}
menuIsOpen={menuIsOpen}
loadOptions={this.loadOptions}
// Let the select field appear as regular input.
components={{DropdownIndicator: null, IndicatorSeparator: null}}
placeholder="Enter your text..."
// Hook into events to make the editing work.
onChange={this.onChange}
onInputChange={this.onInputChange}
onFocus={this.onFocus}
onKeyDown={this.onKeyDown}
onMenuClose={this.onMenuClose}
// Create the new option at the top of the list.
createOptionPosition="first"
/>
)
}
}
Would be interested in a solution for when
isMulti
is enabled. Hitting backspace with the cursors after a selected value should make that value editable instead of outright deleting it.
here's my example for isMulti new example using @Rall3n as a base
https://codesandbox.io/s/react-select-editable-multi-createable-wp13r
My approach by replacing hidden SingleValue and enchanced Input.
import React, { useCallback, useMemo, useState } from "react";
import { components as cs } from "react-select";
import CreatableSelect from "react-select/creatable";
import { colourOptions } from "./docs/data";
const NewSingleValue = () => null;
const NewInput = ({ value: inputValue, isHidden, ...props }) => {
const {
selectProps: { value, getOptionLabel }
} = props;
const label = useMemo(() => {
if (!value) {
return "";
}
return getOptionLabel(value);
}, [getOptionLabel, value]);
const v = useMemo(() => {
if (!inputValue) {
return label;
}
return inputValue;
}, [inputValue, label]);
const hidden = useMemo(() => {
if (v) {
return false;
}
return isHidden;
}, [isHidden, v]);
return <cs.Input isHidden={hidden} value={v} {...props} />;
};
const components = {
...cs,
Input: NewInput,
SingleValue: NewSingleValue
};
const CreatableSingle = props => {
const [value, setValue] = useState(null);
const handleInputChange = useCallback((inputValue, actionMeta) => {
console.group("Input Changed");
console.log(inputValue);
console.log(`action: ${actionMeta.action}`);
console.groupEnd();
}, []);
const handleChange = useCallback((value, actionMeta) => {
console.group("Value Changed");
console.log(value);
console.log(`action: ${actionMeta.action}`);
console.groupEnd();
setValue(value);
}, []);
return (
<CreatableSelect
components={components}
isClearable
onChange={handleChange}
onInputChange={handleInputChange}
options={colourOptions}
value={value}
/>
);
};
export default CreatableSingle;
https://codesandbox.io/s/unr3u
Should work for AsyncCreatable too.
Here is my take at an editable Select.
It's not AsyncCreatable, but should work the same way.
import React, { useState, useRef } from "react";
import Select, { components } from "react-select";
const Input = (props) => <components.Input {...props} isHidden={false} />;
export default function EditableSelect() {
// This needs to become a controlled component so track state
const [value, setValue] = useState();
const [inputValue, setInputValue] = useState("");
const options = useRef([
{ label: "Editable Options", value: 1 },
{ label: "Black Magic", value: 2 },
{ label: "Very Possible ", value: 3 }
]).current;
const selectRef = useRef();
const onInputChange = (inputValue, { action }) => {
// onBlur => setInputValue to last selected value
if (action === "input-blur") {
setInputValue(value ? value.label : "");
}
// onInputChange => update inputValue
else if (action === "input-change") {
setInputValue(inputValue);
}
};
const onChange = (option) => {
setValue(option);
setInputValue(option ? option.label : "");
};
const onFocus = () => value && selectRef.current.select.inputRef.select();
return (
<div style={{ fontFamily: "sans-serif", textAlign: "center" }}>
<Select
ref={selectRef}
options={options}
isClearable={true}
value={value}
inputValue={inputValue}
onInputChange={onInputChange}
onChange={onChange}
onFocus={onFocus}
controlShouldRenderValue={false}
components={{
Input
}}
/>
<button onClick={onFocus} disabled={!value} style={{ margin: "1rem 0" }}>
Hocus Focus!
</button>
</div>
);
}
@cention-sany just a heads up that there is a prop called controlShouldRenderValue
that essentially does the same thing by not rendering the single or multi value component.
That all said, this thread is very similar to many others and I have created a discussion here to better discuss the behavior and perhaps what a prop implementation might look like.
I will close this issue and further discussion about this behavior can be had in the provided link.
Most helpful comment
Is what you both are referring to is the ability to modify an existing selection's text, ie. Say the selected text is "AAAAA" and you want to select "AAAAB" you want to delete the last letter and change it... You can't. You have to delete the whole thing and start again?
If so, then I wholeheartedly agree, this seems like a really silly little bug... @JedWatson any ideas?