Well... onChange responds to the user input. But what I want to achieve is to .select() text in the input field programmatically.
Would you mind sharing an example of how I can get a ref to the input that is embedded inside the react-select?
@manualva7 , with all due respect, this is an issue related to react-select, because the input element that I need is internal to react-select. I have done research as much as I could, and I cannot find how to get a reference to that internal input element, hence my question on SO and here.
If you want to see why I wanted to find a reference to the input element, see the answer on my SO question - someone actually suggested a working solution. I still think it's a bit hacky as it relies on querying for a certain id, which may change, but I'll go with that for now while there isn't a more direct reference to the input element provided.
@artooras I believe you might be looking for the following answer and also replied to the SO post. While the select reference does support a few methods directly on the input element (focus and blur), it does not expose a select method in the same manner.
For that you would need to directly access the inner component input reference which conceptually would look like the following:
selectRef -> current (StateManager) -> select(Select Component) -> inputRef (Input Component)
selectRef.current.select.inputRef.select()
I hope this helps and if so, please consider closing this issue.
Thanks @ebonow . But with your suggestion I get:
TypeError: ref.current.select.inputRef is undefined
I'm calling it right after focus():
ref.current.focus()
ref.current.select.inputRef.select()
@artooras. Sorry for the late reply. I lost my last draft while working on a sandbox solution for you. There are a few things to this....
1) Targeting the input ref also depends on the type of Select. This is a mild annoyance of mine but here's how it's done depending on your use-case...
Select: ref.current.select.inputRef.select()
Createable or Async: ref.current.select.select.inputRef.select()
Createable Async: ref.current.select.select.select.inputRef.select()
2) React-Select clears the input text when an option is selected. You stated that you were able to get a working answer through Stackoverflow, but just wanted to confirm that it worked as you had intended as the onBlur method generally will clear out the input unless you override the behavior.
One of the more asked for requests with React-Select is to expose the inputValue as editable. Here is what I am doing to make this happen which unfortunately involves making React-Select a controlled component. I may take another stab at this by leveraging the StateManager, but for now, this fits my needs.
const [ value, setValue ] = useState();
const [ inputValue, setInputValue ] = useState('');
const onInputChange = (inputValue, { action }) => {
if (action === 'input-blur') {
// onBlur reset label to last selected value label
setInputValue(value ? value.label : '');
}
else if (action === 'input-change') {
setInputValue(inputValue);
}
return;
}
const onChange = option => setValue(option);
<Select
className="react-select--editable"
classNamePrefix="react-select"
value={value}
inputValue={inputValue}
onInputChange={onInputChange}
onChange={onChange}
/>
Then for my CSS I do that following...
.react-select--editable {
.react-select__input input {
opacity: 1 !important;
}
.react-select__control--is-focused {
.react-select__single-value {
display: none;
}
}
}
Here's a version that does not require any extra styling that I tested today found here
@artooras Here is your solution.
@manualva7 100% incorrect. Here is the working "solution" that you said isn't possible: https://codesandbox.io/s/react-select-editable-and-selectable-6nfdv
Please consider reading before refuting so assuredly what's possible and not possible in the future.
To set the record straight, the fact is that React-Select DOES render an Input (when the searchable prop is true). What also does happen is that the opacity is set to 0 based on whether or not it thinks it should display based on a isHidden prop sent to the Input component (see here for the implementation) What we need to do is keep it visible and do away with the SingleValue/MultiValues with the controlShouldRenderValue prop.
If you care to learn, here are some of the other "suggested" approaches that could/should have resolved this with hopes that either someone can point out where proposed solution #1 went wrong or to push for making this a much easier internal solution (autoHideInput to override default behavior, editableInput which could manage these state changes internally, easier to override styling, etc...)
Custom Component: (Does not work today for me on my computer)
const Input = inputProps => <components.Input {...inputProps} isHidden={false} />
<Select components={{Input}} ...>
Creating a Custom Component for Input should work, but when testing today, the controlled component seems to be re-rendering the input on every keypress which results in losing focus and winds up setting the document.activeElement to body instead of the input. I am not sure what changed between testing locally on some existing React-Selects and today's Sandbox, but I had to remove it.
Custom Styling: (Does not work)
styles = { input: css => ({ ...css, opacity: 1 })
<Select styles={{styles}} ...>
Theoretically, this should also work, but the way the Input component was written, overwrites the opacity style based on the prop isHidden which is sent to the Input.
CSS: (Works)
.react-select---editable .react-select__input input { opacity: 1 !important }
<Select className="react-select--editable" classNamePrefix="react-select" ...>
I understand specificity and the stigma around !important but it exists for reasons like this; that being a 3rd party library with no apparent alternatives to overwriting inline styles which affect the desired behavior.
That said, I appreciate having a community so we can help solve similar problems. It's why we are all here. It's just not helpful when so much free time is taken to help others only to blindly discredit the methodology and approach without any thought for what you might be missing.
I've built some cool stuff with this tool there's still a lot that I've learned just this past weekend. Looking forward to building more tools and community together.
Thanks @ebonow . Is the following
Select: ref.current.select.inputRef.select()
Createable or Async: ref.current.select.select.inputRef.select()
Createable Async: ref.current.select.select.select.inputRef.select()
documented anywhere? Because I think it should be :)
In my case, I ended up using a workaround which, though may not be entirely correct, works for me quite reliably. This is based on the assumption that when I call focus() on the react-select, the input that is in focus in document is that of react-select:
ref.current.focus()
document.activeElement?.select()
That actually is quite brilliant and simplistic. Are you using a controlled component by passing in the inputValue? Just curious to how you are maintaining a value in the input that could be selected.
I set defaultInputValue as ... and have it selected, which was my intended use case - the user clicks on a button to add a new value in react-select and, as a result, gets the ... default value selected in the input (and the menu under the input showing Add new value: ...), allowing the user to type straight away.
Thanks for the reply @ebonow and @artooras! I'm going to close this issue for now, please let me know if it should remain open.
Most helpful comment
Thanks @ebonow . Is the following
documented anywhere? Because I think it should be :)
In my case, I ended up using a workaround which, though may not be entirely correct, works for me quite reliably. This is based on the assumption that when I call
focus()on thereact-select, the input that is in focus indocumentis that ofreact-select: