Closed frfroes closed 3 years ago
Hi @frfroes, this behavior could be confusing for some. For example what if the user blurred from the input, but did not want to create an option? With your proposal they would have to delete the entry before they could blur or they would have to remove the entry after it being selected.
Well, @agirton the default behavior would still be to blur from the input without creating an option. The implementer would have to explicitly pass the createNewOptionOnBlur={true}
prop to the Creatable
element in question, therefore taking the responsibility of creating a new option on every blur.
In this case he would only do so if his businesses logic required such behavior, as mine required.
I would also love to see this implemented, I currently use autocomplete just as nice addition, not main feature. user should be able to enter anything he likes, blur the field and just forget about it
Same usecase here, the autocomplete is used as an addition. Love to see this implemented. Thoughts on how to proceed would be welcome, i could then contribute on this.
Plus one for this... would also use it
A strange minor bug in @frfroes 's solution: if you enter an exact value found in the dropdown, it won't add it. (possibly due to the isOptionUnique
check?)
@frfroes On your code above, what is this.selector
? I'd like to implement this in my code too. Thanks!
This doesn't seem to work on v2 or is it just me? @jamcreencia Did you use v1 or v2?
Hi @martimarkov , I'm using v1.
Hi guys, sorry for the absence. I have been very busy with work and college these last months and I have not given the proper attention to the issue which I opened myself. Anyway, I would like to be more engaged with the community from now on and I guess this is a good place to start.
@agirton This issue have gotten some popularity over time, so I guess it's worth opening to PR. I do not have experience contributing to open source, so I have some doubts on how to get started. Should I just clone the repo, do the changes, test everything and open the PR? At least that was what I understood from reading the CONTRIBUTING.md, please correct me if I'm missing something.
@jamcreencia Really sorry for letting you hang. You probably figured it out or got it working somehow by now. Just in case, the answer to your question is:
In React, when you're doing something like ref = {s => this.selector = s}
it's called [callback refs] (https://reactjs.org/docs/refs-and-the-dom.html # callback-refs). Basically you're passing the component instance which you are using the callback ref to attribute in the parent component. So this.selector
is the reference for the instance of Creatable, that way I can invokecreateNewOption ()
imperatively from the instance's API.
Just a note on this, in V2 the onBlur event arg is a synthetic event that has a handle to the input, so you should be able to do this easily on your own with a thin wrapper over your onCreateOption handler: (I haven't fully verified this): The handleBlur functions in your component needs to be:
handleCreate = (value) => {
//Do what you need here to create an new object and set your state
}
handleBlur(event){
this.handleCreate(event.target.value)
}
<Creatable onBlur={this.handleBlur} onBlurResetsInput={false} onCreateOption={this.handleCreate} />
Assuming this works, I wouldn't see the need to add anything more to the new API.
Are there plans to have an option for that?
Hi all,
Thank you everyone who had a part in addressing this question.
I'm now closing this issue as it appears to have been resolved via community comments.
However, if you feel this issue is still relevant and you'd like us to review it, or have any suggestions regarding this going forward - please leave a comment and we'll do our best to get back to you!
@bladey - The option suggested by @andoq doesn't handle use cases of multi-select.
There are a bunch of edge cases around it (when the value already exists, the fact null is returned instead of an empty array, etc).
It would be great if onBlur was passed was also passed the current values (or better yet the same params as onChange). This would make it much easier to implement in user land.
FYI for anyone using multiselect and create on blur. This is our solution, although there are still some edge cases that may be missed
const onBlur = (event) => {
const name = event.target.value
if (name) {
const newValue = {label: name, value: name}
if (Array.isArray(props.value) ) {
// Dont allow duplciate values
if (props.value.find(v => v.value === name)) { return props.onChange(props.value) }
props.onChange([ ...props.value, newValue ])
} else if (props.isMulti) {
props.onChange([ newValue ])
} else {
props.onChange(newValue)
}
}
}
Thanks for your feedback @ro-savage, I appreciate it.
It would be great if onBlur was passed was also passed the current values (or better yet the same params as onChange). This would make it much easier to implement in user land.
Greetings @ro-savage ,
When using onInputChange
, there is an action meta event named input-blur
which would enable you to do exactly as you are suggesting.
const onInputChange = (textInput, { action }) => {
if (action === "input-blur" && !!textInput) {
handleChange(textInput);
}
};
const handleChange = (label) => {
if (options.find((opt) => opt.value === label)) {
return;
}
const option = { label, value: label };
setOptions([...options, option]);
isMulti ? setValue([...(value || []), option]) : setValue(option);
};
Here is the example as a codesandbox: Create Option onBlur
Here is a similar example: Create Option on comma input
Given that the issue is over 3 yrs old and that we have an adequate api to solve this use case as of v2, I will close this issue. If anyone has any other questions or concerns please feel free to share and we can always reopen this and/or work through anything that is unresolved for you.
@ebonow shared a great solution but it does not work with the new version as textInput
is blank when the action
is "input-blur"
In order to achieve this, one option is to save the textInput
in the state (a redux state in my case) on the input-change
action and use that state to call handleChange
on input-blur
action.
Sample Code might look like this:
onInputChange = (textInput, { action }) => {
if (action === 'input-blur') {
const { inputValue } = this.state;
if (inputValue) {
handleChange(inputValue)
this.setState({ inputValue: '' });
}
}
if (action === 'input-change') {
this.setState({ inputValue: textInput });
}
};
@sagar-ranglani
My mistake, I was blurring by tabbing out of the field which of course, selects the value. Here is an updated codesandbox based on your observations.
const [options, setOptions] = useState([
{ label: "Option 1", value: 1 },
{ label: "Option 2", value: 2 },
{ label: "Option 3", value: 3 }
]);
const [value, setValue] = useState();
const [inputValue, setInputValue] = useState();
const handleBlur = () => {
const label = inputValue?.trim() || "";
const optionExists = options.find((opt) => opt.label === label);
if (!label || optionExists) {
return;
}
const option = { label, value: label };
// Add new option to menu list
setOptions([...options, option]);
// Add value to selected options
setValue([...(value || []), option]);
// Clear input value
setInputValue("");
};
const onInputChange = (textInput, { action }) => {
if (action === "input-change") {
setInputValue(textInput);
}
if (action === "input-blur") {
handleBlur();
}
};
const onChange = (selected) => {
setValue(selected);
setInputValue("");
};
return (
<Createable
isMulti
inputValue={inputValue}
value={value}
options={options}
onChange={onChange}
onInputChange={onInputChange}
/>
);
First of of all, thanks for the great work on
react-select
.So, I needed to create a new option on blur with the
Creatable
component, even if the the user didn't executed one of the defaults triggers for the creation (e.g: click on"Create option 'foo'", hit TAB or ENTER).I was able to achieve this using refs and invoking
createNewOption
in my parent component, something like this:I'd like to know if there is any intention of adding a more intuitive support for this, like a
createNewOptionOnBlur
prop for theCreatable
. I will be glad to open a PR if that's the case.