option disabled selected not set as default value in React js dropdown - reactjs

In the dropdown below, why is Select City not appearing in the dropdown as the default selection on page load ? Instead, City1 appears as the default selected option.
I have the options for default coded as :
<option value="" disabled selected>
Select City
</option>
The options are coded in another js file as below:
import React from 'react'
const cityoptions = [
{ value: '1', name: 'City1' },
{ value: '2', name: 'City2' },
{ value: '3', name: 'City3' },
....
The following is the component for dropdown.
import React from 'react'
import PropTypes from 'prop-types'
import Select from '../others/input/select'
import cityOptions from './city-options'
const InputCities = ({ value, change }) => (
<div className="edit_caste_div">
<Select
placeholder="Select option"
value={value}
valueChange={e => change('city', e)}
className="edit_city my2"
>
<option value="" disabled selected>
Select City
</option>
{cityOptions.map((e, key) => {
return <option key={key} value={e.value}>{e.name}</option>
})}
</Select>
</div>
)
InputCities.propTypes = {
value: PropTypes.string.isRequired,
change: PropTypes.func.isRequired,
}

You should add a defaultValue attribute to select and set it to the disabled value
<Select
defaultValue="Select City"
valueChange={e => change('city', e)}
className="edit_city my2"
>
<option value="Select City" disabled>
Select City
</option>
{cityOptions.map((e, key) => {
return <option key={key} value={e.value}>{e.name}</option>
})}
</Select>

Related

How to have second dropdown menu values be dependent on value of first dropdown menu in React render function

In the render function of a React component, I have the following code
<select name="env" id="env">
<option value="Dev">Dev</option>
<option value="Staging">Staging</option>
<option value="Prod">Prod</option>
</select>
<select name="region" id="region">
<option value="option1">op1</option>
<option value="option2">op2</option>
<option value="option3">op3</option>
<option value="option4">op4</option>
</select>
If Dev option is selected in first dropdown, there should only be op1 choice available in the 2nd dropdown. Similarly if Staging is selected, then op1, op2 and op3 are the available choices. If Prod is selected, then all 4 choices are available. How can I achieve this in React?
You should render different region options by env.
const regionsByEnv = {
Dev: ["option1"],
Staging: ["option1", "option2", "option3"],
Prod: ["option1, option2, option3, option4"],
};
const YourComponent = () => {
const [env, setEnv] = useState("");
const regionOptions = useMemo(() => {
if (!env) {
return regionsByEnv.Prod.map((option) => (
<option value={option} key={option}>
{option}
</option>
));
}
return regionsByEnv[env].map((option) => (
<option value={option} key={option}>
{option}
</option>
));
}, [env]);
return (
<>
<select
value={env}
onChange={(e) => setEnv(e.target.value)}
name="env"
id="env"
>
<option value="Dev">Dev</option>
<option value="Staging">Staging</option>
<option value="Prod">Prod</option>
</select>
<select name="region" id="region">
{regionOptions}
</select>
</>
);
};
You should filter option for select region base on selected option of select env. So you can create a state for handling value of select env
export default function App() {
const [select1, setSelect1] = useState("Dev");
const filterOption2 = allOption2.filter((i) => {
return (
(select1 === "Dev" && i.value === "option1") ||
(select1 === "Staging" && i.value !== "option4") ||
select1 === "Prod"
);
});
return (
<div className="App">
<select name="env" id="env" onChange={(e) => setSelect1(e.target.value)}>
<option value="Dev">Dev</option>
<option value="Staging">Staging</option>
<option value="Prod">Prod</option>
</select>
<select name="region" id="region">
{filterOption2.map((op) => (
<option key={select1 + op.value} value={op.value}>
{op.name}
</option>
))}
</select>
</div>
);
}
const allOption2 = [
{
name: "op1",
value: "option1"
},
{
name: "op2",
value: "option2"
},
{
name: "op3",
value: "option3"
},
{
name: "op4",
value: "option4"
}
];
You can check in my codesandbox

React | Select Amount

I have a Dialog where the user is able to create a new Tour. I want to add a Select option to choose the amount of Tours being created. Currently the component is not rerendering onChange and the amount is not being saved. I would really appreciate help :)
My Code looks like this :
const [selectedOption, setSelectedOption] = useState({amount:''});
const handleSelectChange = (event) => {
const amount = event.target.amount;
setSelectedOption({
...selectedOption,
[amount]: event.target.value,
});
};
<FormControl className={classes.formControl}>
<InputLabel
htmlFor="text-simple"
required
>{t('Anzahl Touren')}</InputLabel>
<Select
native
value={selectedOption.amount}
onChange={handleSelectChange}
inputProps={{
amount: 'amount'
}}
>
<option value={1}>1</option>
<option value={2}>2</option>
<option value={3}>3</option>
<option value={4}>4</option>
</Select>
</FormControl>
EDIT:
Getting error: Every child in a list should have a unique key prop.
const numberList = ['1','2','3','4','5']
<FormControl className={classes.formControl}>
<InputLabel
htmlFor="text-simple"
required
>{t('Anzahl Touren')}</InputLabel>
<Select
name="amount"
input={<Input id="text-simple"/>}
required
native
value={selectedOption.amount}
onChange={handleSelectChange}
>
{numberList.map((amount,index) => {
return(
<option
key={index}
value={amount}>
{amount}
</option>
)
})}
</Select>
</FormControl>
Try this approach,
Set a name field for select. And update the state based on the name field.
like below,
<Select
name="amount" <--- Add this change
native
value={selectedOption.amount}
onChange={handleSelectChange}
inputProps={{
amount: "amount"
}}
>
handleSelectChange method:-
const amount = event.target.name;
Complete Code:-
import { FormControl, InputLabel, Select } from "#material-ui/core";
import React, { useState } from "react";
import "./styles.css";
export default function App() {
const [selectedOption, setSelectedOption] = useState({ amount: "" });
const handleSelectChange = (event) => {
console.log(event.target.name, event.target.value);
const amount = event.target.name;
setSelectedOption({
...selectedOption,
[amount]: event.target.value
});
};
return (
<>
<FormControl>
<InputLabel htmlFor="text-simple" required>
Anzahl Touren
</InputLabel>
<Select
name="amount"
native
value={selectedOption.amount}
onChange={handleSelectChange}
inputProps={{
amount: "amount"
}}
>
<option value={1}>1</option>
<option value={2}>2</option>
<option value={3}>3</option>
<option value={4}>4</option>
</Select>
</FormControl>
Selected Amount - {selectedOption.amount}
</>
);
}
Working code - https://codesandbox.io/s/proud-wave-4dz0u?file=/src/App.js:0-1080

import huge option list into main component

I'm using React 16.12, and I have a component that contains a select dropdown box for a form. The option field section is huge...like over 75 choices. With it being so long, I don't want to clutter up my main form component.
So I tried putting it in a separate file called options.js like this:
<option selected>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
But whenever I try to import, I just get this error:
Failed to compile
Parsing error: Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment
<>...</>?
I want it do look something like this in the main form component:
import React from "react";
import "./options" As OptionListing;
const App = () => (
<Form>
<select name="optionTypes">
<OptionListing>
</select>
</Form>
);
render(<App />, document.getElementById("root"));
Is this possible?
Thanks!
This is possible but you need one encapsulating component, try this.
import React from "react";
const OptionList = () => {
return (
<React.Fragment>
<option selected>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</React.Fragment>
)
}
export default OptionList
This is an alternate way of doing the same thing in shorthand (newer React versions)
import React from "react";
const OptionList = () => {
return (
<>
<option selected>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</>
)
}
export default OptionList
https://reactjs.org/docs/fragments.html
try modifying Options.js like below
<React.Fragment>
<option selected>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</React.Fragment>
OR return array of elements like
const options = [
<option selected>Open this select menu</option>,
<option value="1">One</option>,
<option value="2">Two</option>,
<option value="3">Three</option>,
];
and use as
<Form>
<select name="optionTypes">
{options}
</select>
You can create a reusable Select component like this:
export default function Select({ name, options, handleSelected }) {
return (
<select name={name} onChange={e => handleSelected(e.target.value)}>
{options.map(({ key, title }) => (
<option key={key} value={key}>
{title}
</option>
))}
</select>
);
}
App.js
import React from "react";
import Select from "./Select";
const options = [
{
key: 1,
title: "Option 1"
},
{
key: 2,
title: "Option 2"
},
{
key: 3,
title: "Option 3"
}
];
export default function App() {
const onSelected = option => {
console.log(option);
};
return (
<div>
<form>
<Select
name="optionTypes"
options={options}
handleSelected={onSelected}
/>
</form>
</div>
);
}
You can also put the options to a file, and import it to the App.js.
For example:
options.json
[
{
"key": 1,
"title": "Option 1"
},
{
"key": 2,
"title": "Option 2"
},
{
"key": 3,
"title": "Option 3"
}
]
App.js
import React from "react";
import Select from "./Select";
import options from './options.json';
export default function App() {
const onSelected = option => {
console.log(option);
};
return (
<div>
<form>
<Select
name="optionTypes"
options={options}
handleSelected={onSelected}
/>
</form>
</div>
);
}
Codesandbox
If your options fields keys are different from key and title, before passing the options, you may use Array.map() to transform.

how to make option selected by default in react

I am using this.state.something in option tag to make it selected default.
but it is showing me error at this.state.editusertype
<select name="usertype" className="form-control" value={this.state.editusertype}>
<option value="">Select</option>
<option value="Employee" {this.state.editusertype == "Employee" ? "selected" : ""} >Employee</option>
<option value="Manager" {this.state.editusertype == "Manager" ? "selected" : ""}>Manager</option>
</select>
If you want to have a default option, set a default value for your select tag. It should correspond with a matching option. See sandbox: https://codesandbox.io/s/young-pine-zmpvr
class App extends React.Component {
state = {
editusertype: "Manager"
};
handleOnChange = event => {
this.setState({
editusertype: event.target.value
});
};
render() {
return (
<div>
<select
name="usertype"
className="form-control"
onChange={this.handleOnChange}
value={this.state.editusertype}
>
<option value="">Select</option>
<option value="Employee">Employee</option>
<option value="Manager">Manager</option>
</select>
</div>
);
}
}
handleOnChange() is used to change the value upon selection of a different item.
I recommend you use react-select.
const options = [
{ value: '', label: 'Select' },
{ value: 'Employee', label: 'Employee' },
{ value: 'Manager', label: 'Manager' }
];
return (
<Select
name="usertype"
className="form-control"
options={options}
value={this.state.editusertype}
/>
);

Reactjs - Select box with varying first option based on passed attribute

I am trying to show the first option different based on an attribute I pass.
In the search page, I want the user to be able to select "Any" option.
In the edit profile page, "Any" option should not be shown because that is only for search.
Edit profile page
<option value="0" disabled selected>
Select Religion
</option>
Search page
<option value="Any" selected>
Any Religion
</option>
Search profile page has this code:
import React, { Component } from 'react'
..
import ReligionInput from '../edit-profile/religion-input'
..
..
<ReligionInput value={religion} change={this.changeReligion} any="Y" />
...
And ReligionInput has a check for any == Y or not but its not working and always has the Any option. What is wrong with the code below ?
import religionOptions from './religion-options'
const InputReligion = ({ value, change, any }) => (
<div className="edit_religion_div">
<Select
placeholder="Select option"
value={value}
valueChange={e => change('religion', e)}
className="edit_religion my2"
>
{any} == 'Y' ?
`<option value="Any" selected>
Any Religion
</option>` :
`<option value="0" disabled selected>
Select Religion
</option>`
{religionOptions.map((e, key) => {
return <option key={key} value={e.value}>{e.name}</option>;
})}
</Select>
</div>
)
InputReligion.propTypes = {
value: PropTypes.string.isRequired,
change: PropTypes.func.isRequired,
}
All other options come from religionOptions.
A dirty way of doing it would be.
<option value={ any=='Y' ? '0' : 'Any' } selected>{ any=='Y' ? 'select' : 'any religion' }</option>
Yeah, not really a fan of those conditions either.
A cleaner and more readable approach would be:
const InputReligion = (props) => {
let defaultOption = null;
if (props.any == 'Y' ) {
defaultOption = <option value='Any' selected>Any religion</option>
} else {
defaultOption = <option value='0' selected disabled>Select Religion</option>
}
return (
<div className="edit_religion_div">
<select placeholder="Select Option"
className="edit_religion my2"
value={ props.value }
valueChange={ e => change('religion', e)}
>
{ defaultOption }
{
religion.map( (e, key) => {
return <option key={ key } value={ e.value }>{ e.name }</option>
})
}
</select>
</div>
)
}

Resources