I have tried following code, but it sets & gets the entire json of the selected value. How to set & get only the value of the selectedOption & not the entire json of the selectedOption from state after the selection. The code given in the the official documentation is given below:
import React from 'react';
import Select from 'react-select';
const options = [
{ value: 'chocolate', label: 'Chocolate' },
{ value: 'strawberry', label: 'Strawberry' },
{ value: 'vanilla', label: 'Vanilla' }
];
class App extends React.Component {
state = {
selectedOption: null,
}
handleChange = (selectedOption) => {
this.setState({ selectedOption });
console.log(`Option selected:`, selectedOption);
}
render() {
const { selectedOption } = this.state;
return (
<Select
value={selectedOption}
onChange={this.handleChange}
options={options}
/>
);
}
}
you should bind handleChange in constructor
because react-reselect by default bind all methods in code line https://github.com/JedWatson/react-select/blob/master/.babelrc#L4
transform-class-properties in .babelrc bind by default
Do bind like this:
https://medium.freecodecamp.org/react-binding-patterns-5-approaches-for-handling-this-92c651b5af56
And the answer to your question here:
import React from 'react';
import Select from 'react-select';
const options = [
{ value: 'chocolate', label: 'Chocolate' },
{ value: 'strawberry', label: 'Strawberry' },
{ value: 'vanilla', label: 'Vanilla' }
];
class App extends React.Component {
state = {
selectedOption: null,
}
constructor() {
this.handleChange = this.handleChange.bind(this)
}
handleChange = (selectedOption) => {
console.log('selectedOption', selectedOption); // log here before set state
this.setState({ selectedOption });
console.log(`Option selected:`, selectedOption);
}
render() {
const { selectedOption } = this.state;
return (
<Select
value={selectedOption}
onChange={this.handleChange}
options={options}
/>
);
}
}
Best way is to actually make your component wrapper around react-select component example:
const CustomSelect = ({onChange, options, value, isMulti}) => {
return(
<Select
options={options}
onChange={(val) => isMulti
? onChange(val.map((c) => c.value))
: onChange(val.value)
}
value={isMulti
? options.filter((c) => value.includes(c.value))
: options.find((c) => c.value === value)
}
isMulti={isMulti}
/>
)
}
Extract selected value and pass to handler
onChange={(e) => this.handleChange(e.value)}
...
import React from 'react';
import Select from 'react-select';
const options = [
{ value: 'chocolate', label: 'Chocolate' },
{ value: 'strawberry', label: 'Strawberry' },
{ value: 'vanilla', label: 'Vanilla' }
];
class App extends React.Component {
state = {
selectedOption: null,
}
handleChange = (selectedOption) => {
this.setState({ selectedOption });
console.log(`Option selected:`, selectedOption);
}
render() {
const { selectedOption } = this.state;
return (
<Select
value={selectedOption}
onChange={(e) => this.handleChange(e.value)}
options={options}
/>
);
}
}
Related
I made a example in following:
I am new to React and i am using React Select
import React, { Component, Fragment } from "react";
import Select from 'react-select';
const options = [
{ value: 'blues', label: 'Blues' },
{ value: 'rock', label: 'Rock' },
{ value: 'jazz', label: 'Jazz' },
{ value: 'orchestra', label: 'Orchestra' }
];
class DropDown3 extends Component {
constructor(props){
super(props)
this.state = {
selectOptions : [],
id: "",
name: ''
}
}
handleChange = (selectedOption) =>
{
console.log("selected",selectedOption)
this.setState({ selectedOption });
};
render()
{
const { selectedOption } = this.state;
return (
<Fragment>
<Select
options = {options}
onChange ={this.handleChange}
value = {selectedOption}
defaultValue={{ value: 'jazz', label: 'Jazz' }}
/>
<div>Hello you select {this.state.selectedOption}</div>
</Fragment>
);
}
}
export default DropDown3;
what i want is to display what i have selected in the dropdown so that i can pass it to another component.
The abouve code didnt run everytime i choose a menu
and it run only i comment out the
"Hello you select {this.state.selectedOption}"
thanks
You should initialize the selectedOption in the state, and when you update the state you should take the value of the selectedOption object.
import React, { Component, Fragment } from "react";
import Select from "react-select";
const options = [
{ value: "blues", label: "Blues" },
{ value: "rock", label: "Rock" },
{ value: "jazz", label: "Jazz" },
{ value: "orchestra", label: "Orchestra" }
];
class DropDown3 extends Component {
constructor(props) {
super(props);
this.state = {
selectOptions: [],
selectedOption: "",
id: "",
name: ""
};
}
handleChange = (selectedOption) => {
console.log("selected", selectedOption);
this.setState({ selectedOption: selectedOption.value });
};
render() {
const { selectedOption } = this.state;
return (
<Fragment>
<Select
options={options}
onChange={this.handleChange}
value={selectedOption}
defaultValue={{ value: "jazz", label: "Jazz" }}
/>
<div>Hello you select {this.state.selectedOption}</div>
</Fragment>
);
}
}
export default DropDown3;
https://primefaces.org/primereact/showcase/#/autocomplete
I am trying to load suggestions dropdown as soon as component loads with some data in componentDidMount. The suggestionsList is updating with the obj data in componentDidMount, however suggestion dropdown is not showing.
Simply, whenever input is get focussed and no input text is there, a suggestion dropdown should show.
abcCmp.jsx
class abcCmp extends React.Component {
state;
constructor() {
super();
this.state = {
suggestionsList: []
};
}
componentDidMount() {
let obj = [{'color':'red',name: 'Danny', id: '1'}];
this.setState({suggestionsList: [...obj]})
}
render(){
return (
<div className="containerBox">
<AutoComplete suggestions={this.state.suggestionsList}
minLength={1} placeholder="Add People" field="name" multiple={true}
autoFocus={true} />
</div>
)
}
If you gone through documentation there are other parameters also required.
Those are: completeMethod,value,onChange out of these completeMethod is required to show filtered list as you type. Inside completeMethod you need to filter your data that's how your dropdown list reduces as you type more.
You need ref for toggling dropdown functionality and also you need to check on focus if input value is empty and no value is selected so toggle dropdown.
Here is simple POC I create for reference. Try typing D
Code:
import React from "react";
import { AutoComplete } from "primereact/autocomplete";
import "./styles.css";
let obj = [
{ color: "red", name: "Dagny", id: "1" },
{ color: "red", name: "kanny", id: "2" },
{ color: "red", name: "Dgnny", id: "3" },
{ color: "red", name: "Danny", id: "4" },
{ color: "red", name: "Dmnny", id: "5" },
{ color: "red", name: "Donny", id: "" }
];
class MyComponent extends React.Component {
myRef = React.createRef();
constructor() {
super();
this.state = {
suggestionsList: [],
selected: null,
inputValue: null
};
}
componentDidMount() {
this.setState({ suggestionsList: [...obj] });
}
searchList = (event) => {
let suggestionsList;
if (!event.query.trim().length) {
suggestionsList = [...obj];
} else {
suggestionsList = [...obj].filter((list) => {
return list.name.toLowerCase().startsWith(event.query.toLowerCase());
});
}
this.setState({ suggestionsList });
};
render() {
return (
<div className="containerBox">
<AutoComplete
suggestions={this.state.suggestionsList}
completeMethod={this.searchList}
minLength={1}
ref={this.myRef}
dropdown
inputId="my"
placeholder="Add People"
field="name"
onFocus={(e) => {
if (!this.state.inputValue && !this.state.selected) {
this.myRef.current.onDropdownClick(e, "");
}
}}
onKeyUp={(e) => this.setState({ inputValue: e.target.value })}
// completeOnFocus={true}
multiple={true}
autoFocus={true}
value={this.state.selected}
onChange={(e) => this.setState({ selected: e.value })}
/>
</div>
);
}
}
export default function App() {
return (
<div className="App">
<MyComponent />
</div>
);
}
Demo: https://codesandbox.io/s/prime-react-autocomplete-forked-n3x2x?file=/src/App.js
Add dropdown inside autocomplete tags and also add completeMethod and bind it to a search/filter function, add a value to bind the selected value, add a onChange function to it
You can find full documantation and working example here :PrimeFaces React Autocomplete
I want to render options in select dynamically from the list.
If option already used I want to mark it as isUsed: true.
I mean change state of <Wrapper />
this.state = {
options: {
One: {value: "one", isUsed: false},
Two: {value: "two", isUsed: false},
Three: {value: "three", isUsed: false}
}
What is the best way?
I'm trying to mark it using componentDidMount() using markUsed() (for testing purpose there is static key "One"), but how do I get the current mounted option, to mark dynamic key in this.state?
I've tried to console.log(this) in componentDidMount(), but it seems like it doesn't contain current mounted option value.
import React from 'react';
import ReactDOM from 'react-dom';
class Input extends React.Component {
componentDidMount = () => {
console.log(this);
this.props.markUsed();
}
render() {
let options = Object.keys(this.props.list).map((item,i) => {
if (!this.props.list[item].isUsed) {
return(
<option key={i} value={this.props.list[item].value}>{item}</option>
)
}
});
return (
<div>
<select>
{options}
</select>
<input type="text" />
</div>
)
}
}
class Wrapper extends React.Component {
constructor(props) {
super(props);
this.markUsed = this.markUsed.bind(this);
this.state = {
options: {
One: {value: "one", isUsed: false},
Two: {value: "two", isUsed: false},
Three: {value: "three", isUsed: false}
},
inputs: []
}
}
markUsed = () => {
this.setState(prevState =>({
options: {
...prevState.options,
One: {
...prevState.options.One,
isUsed: true
}
}
}));
}
addInput = (e) => {
this.setState((prevState) => ({
inputs: [...prevState.inputs, {option: "", value: ""}],
}));
}
render() {
return(
<div>
{
this.state.inputs.map((val, idx) => {
return (
<div key={idx}>
<Input list={this.state.options} markUsed={this.markUsed} />
</div>
)
})
}
<button type="button" onClick={this.addInput}>add</button>
</div>
)
}
}
ReactDOM.render(<Wrapper />, document.getElementById('root'));
Here is a generic solution where you pass a target to be marked:
markUsed = target => {
const [key, keyValue] = Object.entries(this.state.options).find(
([, keyValue]) => keyValue.value === target
);
keyValue.isUsed = true;
this.setState(prevState => ({
...prevState,
options: { ...prevState.options, [key]: keyValue }
}));
};
Therefore you need to pass a target value like one,two,three etc.
class Input extends React.Component {
state = {
...
};
render() {
const { markUsed } = this.props;
const options = Object.keys(this.props.list).map((item, i) => {
if (!this.props.list[item].isUsed) {
if (this.props.list[item].value === this.state.currValue) {
markUsed(this.state.currValue);
}
return ...
}
});
return (
<>
<select
value={this.state.value}
onChange={e => {
e.persist();
const currValue = e.target.value;
markUsed(currValue);
this.setState({ currValue });
}}
>
...
</>
);
}
}
I can't unselect the default values I have set in state.
I'm pulling from an example in Grommet's codesandbox.
Only change thus far is adding an object array instead of an array of strings. See VALUE prop in docs mention object array..
const OPTIONS = [
{
label: "Expansion",
value: "1"
},
{
label: "Rollout",
value: "2"
}
];
export default class extends Component {
state = {
value: [
{
label: "Rollout",
value: "2"
}
],
options: OPTIONS
};
render() {
const { options, value } = this.state;
return (
<Select
multiple={true}
value={value}
labelKey="label"
valueKey="value"
onSearch={searchText => {
const regexp = new RegExp(searchText, "i");
this.setState({ options: OPTIONS.filter(o => o.match(regexp)) });
}}
onChange={event => {
console.log({ event });
this.setState({
value: event.value,
options: OPTIONS
});
}}
options={options}
/>
);
}
}
In the logs, I'm getting selected: [ -1, 1 ] when I attempt to unselect the Rollout option, and Rollout is still visually highlighted/selected in the view.
Here is your working code, You need to check if currently clicked value is already there in selection then remove it from values and if it is not in selected then add in values.
I changed onChange function as below.
Let me know if any issues.
import React, { Component } from "react";
import { Select } from "grommet";
import SandboxComponent from "./SandboxComponent";
const OPTIONS = [
{
label: "Expansion",
value: "1"
},
{
label: "Rollout",
value: "2"
}
];
export default class extends Component {
state = {
value: [
{
label: "Rollout",
value: "2"
}
],
options: OPTIONS
};
render() {
const { options, value } = this.state;
return (
<Select
multiple={true}
value={value}
labelKey="label"
valueKey="value"
selected={0}
onSearch={searchText => {
const regexp = new RegExp(searchText, "i");
this.setState({ options: OPTIONS.filter(o => o.match(regexp)) });
}}
onChange={event => {
let isExist = value.find(item => {
return item.value === event.option.value;
});
let newValue;
if (isExist) {
newValue = value.filter(item => {
return item.value !== event.option.value;
});
} else {
newValue = value;
newValue.push(event.option);
}
this.setState({
value: newValue
});
}}
options={options}
/>
);
}
}
import React from 'react';
import Select from 'react-select';
const options = [
{ value: 'all', label: 'all' },
{ value: 'destroyed', label: 'Destroyed' },
{ value: 'damaged', label: 'Damaged' },
{ value: 'physicalDamage', label: 'PhysicalDamage' }
]
class SearchFilters extends React.Component {
_onChange = (e, options) => {
const onChangeData = {
value: e.value,
name: e.label,
result: options.find(item => item.value === e.value)
};
console.log(onChangeData.value);
return onChangeData;
};
render(){
return(
<div>
<Select
options={options}
onChange={e => this._onChange(e, options)}
isMulti={true}
/>
</div>
)
}
}
export default SearchFilters
From the above code if isMulti is false in select, I'm able to print the value of the selected option in console, but if I change it to true, I get the value as undefined.
I need help in fixing this. Thanks in advance.
Ouput: