Closed Falenos closed 5 years ago
@Falenos Same here. Here's a gnarly workaround for you - this is MobX code, so yours may be a bit different.
Grab a ref to the creatable component like so
<Creatable
disabled={saving || frozen}
placeholder="Tag this section"
ref={el => this.creatableEl = el} // <-------- here
onNewOptionClick={obj => store.addNewTag(obj, this.creatableEl)}
onChange={store.setTags}
value={store.rawTags}
multi={true}
options={sectionTagStore.allTags} />
and then
@action addNewTag = (obj, creatableEl) => {
this.tags.push(sectionTagStore.createTag(obj));
creatableEl.select.setState({inputValue: ''}); // <------- clears the input text
}
So the ref to the Creatable component has a select property on it which (I assume) is the underlying multi component. Set its state's inputValue
to empty string to clear the input text. And done.
@arackaf thanks a lot for the tip. It got me really close but still not there, it really is a bit gnarly though. I am relatively new in react and from your suggestion I checked out refs for the first time...
What happened is that my component that renders the "Select" is stateless and is not declared as a Class maybe that's why it's not working, but I need to research further. The creatableEl.select.setState(); gives me nothing. There is a State object in Select so creatableEl.select.State exists but the .setState() method is not available. The code is below, if you have any suggestions...
import React, { PropTypes } from "react";
import Select from "react-select";
function TagSelect(props) {
const handleNewCategoryTagSave = (tag)=> {
// Blank tags cannot be saved
if ((!tag || !tag.value) ||
(typeof tag.value === "string" && tag.value.trim().length === 0)) {
return false;
}
props.onNewCategoryTagSave(props.productId, tag.value, props.name);
};
const selectValue = ()=> {
const value = props.value;
const multiSelect = props.multi;
if (!multiSelect && Array.isArray(value)) {
return props.value[0];
}
return value;
}
return (
<Select.Creatable
multi={props.multi}
name={props.name}
options={props.options}
placeholder={props.placeholder}
value={selectValue()}
onChange={(value) => props.onChange(value, props.name)}
onNewOptionClick={handleNewCategoryTagSave}
/>
);
}
TagSelect.propTypes = {
multi: PropTypes.bool,
name: PropTypes.string,
onChange: PropTypes.func,
onNewOptionClick: PropTypes.func,
options: PropTypes.arrayOf(PropTypes.object),
placeholder: PropTypes.string,
value: PropTypes.any
};
export default TagSelect;
@Falenos not sure. You should be able to add the ref to the Creatable in your SFC, and then whatever event handler that needs to use it would be called from within the closure, with access to the ref.
At this point though I'd just make your component a class; I don't see any real value to making an SFC bloated like that. imo SFCs fit better with simpler components that aren't doing very much.
@arackaf will do and get back on you, thanks
Just ran into this issue, the suggestion worked perfectly. Thanks for that, @arackaf. Would be neat if the input was cleared automatically by default, but not sure what other kinds of issues that might create.
@arackaf I ran into this, too. I'm relatively new to the library; is this low-hanging fruit for contributors, or are there a bunch of edgy cases that would trip me up if I tried? I'm also using react-select
in a stateless component, so adding this.some_ref
breaks my paradigm a bit.
@smelted-code there are currently 133 open pull requests. I'd advise you NOT to PR this unless the owner of this project tells you he'll accept it. I mean, if you want to try to fix it just to see if you can, and won't mind if the PR is ignored, then go for it. But don't go trying to fix it unless you're ok with the PR lingering for a bit.
No offense intended to the project's owner. We all have limited time during the week - I just don't want a new contributor to get frustrated :)
@arackaf I made progress on the issue with a different approach.
Because we needed some functionality that wasn't there either way, like being able to delete the Options
form the dropdown Menu
we forked it and we will release our enhanced version probably by the end of the month from @artlimes, in case you are interested.
Eitherway from my current knowledge of how thing work this is what I saw.
There is a method in Select.js calledselectValue()
. It is called whenever an Option
is selected and clears the Select state property inputValue
. This method is NOT called when you add a new Option
.
If you decide to make your own fork or edit the core somehow like we did, my first approach was to create a new method in Select.js
e.g clearInput that simply this.setState({inputValue: ''})
. Then you can call it from Creatable.js
at
createNewOption () {
if (isOptionUnique) {
if (onNewOptionClick) {
onNewOptionClick(option);
// Our addition. Clears the input values on click.
this.select.clearInput(option);
} else {
...
}
}
}
},
There are also 2 boolean props that might become handy if you pass them to Select from you app.
These are onBlurResetsInput
and onCloseResetsInput
. The onCloseResetsInput
refers to the situations when the dropdown Menu
is closing.
So, my current approach is calling the existing Select closeMenu()
method fromCreatable.js
instead of our custom clearInput
and combine it with a onCloseResetsInput={true}
. This is fine for our usecase but as you can imagine, it closes the Menu when a new option is created.
My general advice would be to check the methods that setState({inputValue: ''})
and figure out which one you want to use. Hope this helped, cheers
@Falenos - thanks a ton for the info. This project is great - look forward to seeing what's ahead for it.
The following worked for me :
<Select.Creatable
name="sticker_categories"
value={this.state.categories}
options={this.state.categoriesSuggestions}
multi={true}
simpleValue={false}
joinValues={true}
// loadOptions={this.getTags}
onChange={this.onCategoriesSelectChange.bind(this)}
promptTextCreator={ label => `Create category "${label}"`}
onNewOptionClick={this.onCreateNewCategory.bind(this)}
newOptionCreator={ o => { return {label: o.label, value: o.label.toLowerCase() } } }
ref={ s => this.selector = s}
/>
Notice the ref attribute is a function that stores the component into this.selector variable Then I have something like this for the onNewOptionClick handler:
onCreateNewCategory(newCatg){
console.log(this.selector);
console.log(newCatg);
const catgs = [].concat(this.state.categories, newCatg);
this.setState({ categories : catgs})
this.selector.select.selectValue(); // this.selector points to the component itself and makes its methods available
}
@josefano thanks for that, it almost entirely worked for me. I found that in my onChange
function the value included an undefined
element. Easy to filter that out and work around this annoying issue!
I am closing this :) i think the discussion is obsolete at this point
For reasons unknown the input field of a mutiselect creatable field is not cleared after new tag creation. I click on create newTag, newTag is displayed on the field and next to it the input stays as is
Is there a method I can call when a new tag is stored to clear the input?
I know its supposed to work by default, but in my case it is not happening.