Select element doesn't have a default value - javascript

I created a form with redux-form. It works correctly but if I don't change select (I'll leave the default value), the value won't send, but if I change the value it will be sent in post method.
export const mySelect = (props) => {
const mySelectOptions = (key, index) => {
return (
<option key={props.options[key].id} value={props.options[key].id}>
{props.options[key].name}
</option>
);
};
if (props && props.options) {
return (
<div className="mv3 w-100">
<div className="b sans-serif pv2 w-100">{props.label}</div>
<select
{...props.input}
className="pa2 input-reset ba b--black-40 w-100"
>
{Object.keys(props.options).map(renderSelectOptions)}
</select>
</div>
);
}
return <div></div>;
};
Example
<Field
name="gender"
label="gender"
component={input.mySelect}
options={[
{
id: 1,
name: "male",
},
{
id: 2,
name: "female",
},
]}
/>;
I tried to set a default value in my SQL table but every time it sends null. Do you know how can I solve my problem?

Related

Reusable Select Form Component Undefined Value

I have a reuseable component i created and the value is undefined. I console logged the currentTarget in the Select.tsx and it returns the value correctly. However, the actual component using the select is the one that returns an undefined value. What am i missing here?
This is the code in the select.Tsx
export const Select = (props: any) => {
const [data] = useState(props.data);
const [selectedData, updateSelectedData] = useState('');
function handleChange(event: any) {
updateSelectedData(event.currentTarget.value);
console.log(event.currentTarget.value, 'in select.tsx line 10');
if (props.onSelectChange) props.onSelectChange(selectedData);
}
let options = data.map((data: any) => (
<option key={data.id} value={data.id}>
{data.label}
</option>
));
return (
<>
<select
className={props.className ? props.className : 'float-right rounded-lg w-[50%] '}
onChange={handleChange}>
<option>Select Item</option>
{options}
</select>
</>
);
};
This is the code being used in the actual component...
...
const actionSelectOptions = [
{ id: 1, label: 'Pricing Revised', value: 'Pricing Revised' },
{ id: 2, label: 'Cost Build-up Posted', value: 'Cost Build-up Posted' },
{ id: 3, label: 'Pricing Created', value: 'Pricing Created' },
];
function onSelectChange(event: any) {
console.log(event.currentTarget.value);
}
return (
...
<Select
className="flex justify-center items-center rounded-lg"
data={actionSelectOptions}
onSelectChange={onSelectChange}
/>
...
)
I tried changing between target and currenTarget in the main component. It both get undefined.. the console works in the select component it seems as if the data is not passing on as its suppose to.
I also tried writing an arrow function within the actual called component for example:
<Select
...
onSelectChange={(e)=> console.log(event.currentTarget)}

How to make a select input that is dependent on other inputs to always show a default value in React?

I have two radio buttons: radio1 and radio2, and one select input.
The Select values depend on the radio buttons.
I want to set the select value to 1 whenever I select radio1.
I've tried setting defaultValue and value to the select input but every time I switch back to radio1 from radio2, the value is always set to 2.
Here's my code, any help is truly appreciated:
import "./styles.css";
import { useState } from "react";
const selectItems = {
name: "size",
fields: {
radio1: [
{
value: "1"
},
{
value: "2"
}
],
radio2: [
{
value: "2"
},
{
value: "3"
},
{
value: "4"
}
]
}
};
const App = () => {
const [values, setValues] = useState({ radio: "radio1", select: "2" });
const handleChange = (name, value) => {
setValues((s) => {
return { ...s, [name]: value };
});
};
return (
<div className="App">
<h2>
How do I make the Select always be '1' when Radio1 is selected after
selecting Radio2?
</h2>
<input
type="radio"
id="radio1"
value="radio1"
name="radio"
onChange={() => handleChange("radio", "radio1")}
/>
<label htmlFor="radio1">Radio1</label>
<input
type="radio"
id="radio2"
value="radio2"
name="radio"
onChange={() => handleChange("radio", "radio2")}
/>
<label htmlFor="radio2">Radio2</label>
<br />
<select
id="size"
name="size"
onChange={(e) => handleChange("select", e.target.value)}
>
{selectItems.fields[values.radio].map(({ value }) => {
return (
<option key={value} value={value}>
{value}
</option>
);
})}
</select>
</div>
);
};
export default App;
example: https://codesandbox.io/s/goofy-danny-p1l3s?file=/src/App.js:0-1460
Edit:
As suggested by some answers, I have tried setting 'selected' as true. In fact, I have tried this before and forgot to mention it on my question. This seem to work, it gives me the desired effect on the browser, but then I get this error on the console:
Warning: Use the `defaultValue` or `value` props on <select> instead of setting `selected` on <option>.
The main problem here is <option> is taking the same key value. When you are selecting radio2, key becomes 2.Then you are selecting radio1 and for that <select> has <option> with key=2. That is why <select> value not changing. The proof is if you change all <option> values unique, example for radio1 {1, 2} and for radio2 {3, 4, 5} your code works fine.
There may be multiple workarounds but the proper way to solve this is having unique id for each of the <option>.
const selectItems = {
name: "size",
fields: {
radio1: [
{
value: "1",
id: 1
},
{
value: "2",
id: 2
}
],
radio2: [
{
value: "2",
id: 3
},
{
value: "3",
id: 4
},
{
value: "4",
id: 5
}
]
}
};
------------------------------------------
<select
id="size"
name="size"
onChange={(e) => handleChange("select", e.target.value)}
>
{selectItems.fields[values.radio].map(({ value, id }) => {
return (
<option key={id} value={value}>
{value}
</option>
);
})}
</select>
Element <option> has property selected that is responsible for determining which item is currently selected.
That is the property that will help you to decide which item should be currently selected at any given time.
To illustrate this, I have added the following check to your element:
<element selected={value === '1'}> and now every time you change the radio from radio1 to radio2 the value changes to 1 as you asked in your question.
My response here is more of a guidance, do not treat as exact step by step instruction as I did not think of any other ways that your program might work or handle different behaviours.
You can define a new state which is called defaultValue. As a result, with setting the value property of select tag by defaultValue, you can achieve your goal:
const App = () => {
const [values, setValues] = useState({ radio: "radio1", select: "2" });
const [defaultValue, setDefaultValue] = useState(0);
const handleChange = (name, value) => {
setValues((s) => {
return { ...s, [name]: value };
});
};
useEffect(() => {
setDefaultValue(selectItems.fields[values.radio][0].value);
}, [values]);
return (
<div className="App">
<h2>
How do I make the Select always be '1' when Radio1 is selected after
selecting Radio2?
</h2>
<input
type="radio"
id="radio1"
value="radio1"
name="radio"
onChange={() => handleChange("radio", "radio1")}
/>
<label for="radio1">Radio1</label>
<input
type="radio"
id="radio2"
value="radio2"
name="radio"
onChange={() => handleChange("radio", "radio2")}
/>
<label for="radio2">Radio2</label>
<br />
<select
id="size"
name="size"
value={defaultValue}
onChange={(e) => handleChange("select", e.target.value)}
>
{selectItems.fields[values.radio].map(({ value }, index) => {
return (
<option key={value} value={value}>
{value}
</option>
);
})}
</select>
</div>
);
};
export default App;

How do I select value and options (label names) are invisible from react-select dropdown?

I am new to React. I'm using react-select and I've used the following code. The dropdown is displayed but I'm unable to see names and unable to view after selecting.
<Select
variant="outlined"
margin="normal"
fullWidth
value={this.state.selected}
options={RewardAutomationsList}
name="selected"
onChange={this.handleChange}
placeholder='None'
>
{RewardAutomationsList.map((option) => (
<option key={option.id} value ={option.name} label={option.name}>
{option.name}
</option>
))}
</Select>
handleChange = event => {
this.setState({
selected: event.name
});
};
The RewardAutomationsList looks like this:
RewardAutomationsList:
0:{name: "TEST 1 (INR 100)", id: "123"}
1:{name: "test 2 (INR 250)", id: "456"}
Can someone help with this?
same npm package use like this block code.
import React, { Component } from 'react'
import Select from 'react-select'
const options = [
{ value: 'chocolate', label: 'Chocolate' },
{ value: 'strawberry', label: 'Strawberry' },
{ value: 'vanilla', label: 'Vanilla' }
]
const MyComponent = () => (
<Select options={options} />
)
react-select accepts an array of objects having label and value keys. Your option objects in RewardAutomationsList have id and name keys, so it can't be displayed. You need to change them.
Also, when you subscribe to change events with react-select's onChange prop, the callback function you provide receives the selectedOption, not the event.
The following should work:
const RewardAutomationsList = [
{ label: "TEST 1 (INR 100)", value: "123" },
{ label: "test 2 (INR 250)", value: "456" },
];
class App extends React.Component {
state = {
selected: null,
}
handleChange = (selectedOption) => {
this.setState({
selected: selectedOption,
});
};
render() {
return (
<React.Fragment>
<Select
fullWidth
margin="normal"
name="selected"
onChange={this.handleChange}
options={RewardAutomationsList}
placeholder="None"
value={this.state.selected}
variant="outlined"
/>
{/* It's not necessary and it's only here to show the current state */}
<pre>{JSON.stringify(this.state, null, 2)}</pre>
</React.Fragment>
);
}
}

How can I pass multiple value by select in reactjs

I need to pass multiple value by using onChange when I select the option, but I can not select single option . it select whole objects .
Here is my code .
const test = [{id:1, name:'test, value:{x:10}}]
<Select
showSearch
style={{ width: 200 }}
placeholder="Select a person"
optionFilterProp="children" >
{test.map(item =>(
<Option value={item.id, item.value}>{item.name}</Option>
))}
</Select>
is there an alternative solution to fix this problem
Use Custom select instead of select.
add multiple values in "eventKey" and on select handler you will find that value array.
import { ButtonToolbar,DropdownButton,MenuItem } from "react-bootstrap";
<ButtonToolbar className="snap-fitness-wrapper">
<DropdownButton
title={this.state.selectedFacilityName}
onSelect={this.onSelectFacility}
id="snap" >
{
this.state.facilities.map(facility => (
<MenuItem
key={facility.facilityId}
eventKey={[facility.facilityId, facility.name]}
value={facility.facilityId}
> {facility.name} - {facility.facilityId}{" "}
</MenuItem>
))
}
</DropdownButton>
</ButtonToolbar>
You can try below code.
const test = [{id:1, name:'test, value:{x:10}}]
<Select
multiple
showSearch
style={{ width: 200 }}
placeholder="Select a person"
optionFilterProp="children" >
{test.map(item =>(
<Option value={item.id, item.value}>{item.name}</Option>
))}
</Select>
If you are using react-select you can add isMulti common props to enable multiple selection for your option , please refer: https://react-select.com/props
BTW, react-select default use value label match, you have to remap for your case
const options = [
{ id: 1, name: 'test1', value:{x:10} },
{ id: 2, name: 'test2', value:{x:20} },
]
<Select
... // other code
isMulti
getOptionValue={option => option.value.x}
/>
It support multiple select , sample link : sandbox
I suppose you are using antd for select and want to get the object properties inside handleChange of select.
A simple method would be to send the id or other parameter and get the object through that.
import React from "react";
import ReactDOM from "react-dom";
import { Select } from "antd";
import "./styles.css";
const { Option } = Select;
const test = [
{ id: 1, name: "test1", value: { x: 10 } },
{ id: 2, name: "test2", value: { x: 11 } },
{ id: 3, name: "test3", value: { x: 12 } }
];
class App extends React.Component {
handleChange = id => {
const clickedOption = test.find(item => item.id === id);
const value = `${clickedOption.id}, ${clickedOption.value.x}`;
console.log(value);
};
render() {
return (
<div className="App">
<Select
onChange={this.handleChange}
style={{ width: 200 }}
placeholder="Select a person"
optionFilterProp="children"
>
{test.map((item, index) => (
<Option value={item.id} key={index}>
{item.name}
</Option>
))}
</Select>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Hope that helps!!!
The simple way of doing this can be like this:
let options = test.map(item => {
return <option value={item.value} onClick={(item) => this.yourhandlerfunction(item)}>item.name</option>
})
render(){
return(
<Select>
{options}
</Select>
)
}
Hope this helps!
You can just pass a second variable in onChange=((e) => this.handleChange(e, item.value) property
const handleChange = (event, itemValue) => {
console.log(`id: ${event.target.value}, value: ${itemValue}`)
}
const test = [{id:1, name:'test', value:{x:10}}]
<Select
multiple
showSearch
style={{ width: 200 }}
placeholder="Select a person"
optionFilterProp="children"
onChange={(e) => this.handleChange(e, item.value)}
>
{test.map((item) =>(
<Option key={key} value={item.id}>{item.name}</Option>
))}
</Select>

How do I create a dynamic drop down list with react-bootstrap

The example code in the react-bootstrap site shows the following. I need to drive the options using an array, but I'm having trouble finding examples that will compile.
<Input type="select" label="Multiple Select" multiple>
<option value="select">select (multiple)</option>
<option value="other">...</option>
</Input>
You can start with these two functions. The first will create your select options dynamically based on the props passed to the page. If they are mapped to the state then the select will recreate itself.
createSelectItems() {
let items = [];
for (let i = 0; i <= this.props.maxValue; i++) {
items.push(<option key={i} value={i}>{i}</option>);
//here I will be creating my options dynamically based on
//what props are currently passed to the parent component
}
return items;
}
onDropdownSelected(e) {
console.log("THE VAL", e.target.value);
//here you will see the current selected value of the select input
}
Then you will have this block of code inside render. You will pass a function reference to the onChange prop and everytime onChange is called the selected object will bind with that function automatically. And instead of manually writing your options you will just call the createSelectItems() function which will build and return your options based on some constraints (which can change).
<Input type="select" onChange={this.onDropdownSelected} label="Multiple Select" multiple>
{this.createSelectItems()}
</Input>
My working example
this.countryData = [
{ value: 'USA', name: 'USA' },
{ value: 'CANADA', name: 'CANADA' }
];
<select name="country" value={this.state.data.country}>
{this.countryData.map((e, key) => {
return <option key={key} value={e.value}>{e.name}</option>;
})}
</select>
bind dynamic drop using arrow function.
class BindDropDown extends React.Component {
constructor(props) {
super(props);
this.state = {
values: [
{ name: 'One', id: 1 },
{ name: 'Two', id: 2 },
{ name: 'Three', id: 3 },
{ name: 'four', id: 4 }
]
};
}
render() {
let optionTemplate = this.state.values.map(v => (
<option value={v.id}>{v.name}</option>
));
return (
<label>
Pick your favorite Number:
<select value={this.state.value} onChange={this.handleChange}>
{optionTemplate}
</select>
</label>
);
}
}
ReactDOM.render(
<BindDropDown />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root">
<!-- This element's contents will be replaced with your component. -->
</div>
// on component load, load this list of values
// or we can get this details from api call also
const animalsList = [
{
id: 1,
value: 'Tiger'
}, {
id: 2,
value: 'Lion'
}, {
id: 3,
value: 'Dog'
}, {
id: 4,
value: 'Cat'
}
];
// generage select dropdown option list dynamically
function Options({ options }) {
return (
options.map(option =>
<option key={option.id} value={option.value}>
{option.value}
</option>)
);
}
<select
name="animal"
className="form-control">
<Options options={animalsList} />
</select>
Basically all you need to do, is to map array. This will return a list of <option> elements, which you can place inside form to render.
array.map((element, index) => <option key={index}>{element}</option>)
Complete function component, that renders <option>s from array saved in component's state. Multiple property let's you CTRL-click many elements to select. Remove it, if you want dropdown menu.
import React, { useState } from "react";
const ExampleComponent = () => {
const [options, setOptions] = useState(["option 1", "option 2", "option 3"]);
return (
<form>
<select multiple>
{ options.map((element, index) => <option key={index}>{element}</option>) }
</select>
<button>Add</button>
</form>
);
}
component with multiple select
Working example: https://codesandbox.io/s/blue-moon-rt6k6?file=/src/App.js
A 1 liner would be:
import * as YourTypes from 'Constants/YourTypes';
....
<Input ...>
{Object.keys(YourTypes).map((t,i) => <option key={i} value={t}>{t}</option>)}
</Input>
Assuming you store the list constants in a separate file (and you should, unless they're downloaded from a web service):
# YourTypes.js
export const MY_TYPE_1="My Type 1"
....
You need to add key for mapping otherwise it throws warning because each props should have a unique key. Code revised below:
let optionTemplate = this.state.values.map(
(v, index) => (<option key={index} value={v.id}>{v.name}</option>)
);
You can create dynamic select options by map()
Example code
return (
<select className="form-control"
value={this.state.value}
onChange={event => this.setState({selectedMsgTemplate: event.target.value})}>
{
templates.map(msgTemplate => {
return (
<option key={msgTemplate.id} value={msgTemplate.text}>
Select one...
</option>
)
})
}
</select>
)
</label>
);
I was able to do this using Typeahead. It looks bit lengthy for a simple scenario but I'm posting this as it will be helpful for someone.
First I have created a component so that it is reusable.
interface DynamicSelectProps {
readonly id: string
readonly options: any[]
readonly defaultValue: string | null
readonly disabled: boolean
onSelectItem(item: any): any
children?:React.ReactNode
}
export default function DynamicSelect({id, options, defaultValue, onSelectItem, disabled}: DynamicSelectProps) {
const [selection, setSelection] = useState<any[]>([]);
return <>
<Typeahead
labelKey={option => `${option.key}`}
id={id}
onChange={selected => {
setSelection(selected)
onSelectItem(selected)
}}
options={options}
defaultInputValue={defaultValue || ""}
placeholder="Search"
selected={selection}
disabled={disabled}
/>
</>
}
Callback function
function onSelection(selection: any) {
console.log(selection)
//handle selection
}
Usage
<div className="form-group">
<DynamicSelect
options={array.map(item => <option key={item} value={item}>{item}</option>)}
id="search-typeahead"
defaultValue={<default-value>}
disabled={false}
onSelectItem={onSelection}>
</DynamicSelect>
</div>

Categories