'How to get a certain data in the second autocomplete input that depend on what typed in the first input in React.js?
Okay, so I don't know how to properly express my simple problem because of how simple it is, I guess.
Basically, I have an autocomplete done by me in my React project.. I have two inputs "Country" and "City". When I type a country my autocomplete works great giving me suggestions but now I have to make the same for my second input so it would give me a list of cities that depends on which country is typed in the "Country" input...
"United Kingdom" => "London, Birmingham, Bighton etc."
How can I do that? Thank you!
P.S. I already have all the lists of countries and cities, I just don't know how to make the second input to depend on an information in the first one.
Code here
Autocomplete.jsx https://github.com/lembas-cracker/Weather-app/blob/master/src/Autocomplete.jsx
Form.jsx https://github.com/lembas-cracker/Weather-app/blob/master/src/Form.jsx
Solution 1:[1]
P.S. I already have all the lists of countries and cities, I just don't know how to make the second input to depend on an information in the first one.
If you know which country the city belongs to (perhaps via a key in the city object), you could run a simple filter function to remove any cities that don't belong to that country.
this.state = {
selectedCountry: 'London',
};
const cities = [
{ name: "Toronto", country: "Canada" },
{ name: "London", country: "United Kingdom" }
];
const filteredCities = cities.filter(city => {
return city.country !== this.state.selectedCountry;
});
On your city input field make sure to create an onBlur function to will run the filter on your cities list once the user leaves that input field.
Solution 2:[2]
Made a quick example. Did you mean smth like this? Since you haven't provided any part of your source code, I used plain HTML select for the demo.
https://jsfiddle.net/arfeo/n5u2wwjg/204186/
class App extends React.Component {
constructor() {
super();
this.state = {
countryId: 1,
};
}
onCountryChange(countryId) {
this.setState({ countryId: parseInt(countryId) });
}
render() {
return (
<div>
<Input
key="countriesInput"
type="countries"
countryId={this.state.countryId}
onChange={(countryId) => this.onCountryChange(countryId)}
/>
<Input
key="citiesInput"
type="cities"
countryId={this.state.countryId}
/>
</div>
);
}
}
class Input extends React.Component {
constructor() {
super();
this.selectRef = null;
}
renderOptions() {
const countries = [
{
id: 1,
name: 'England',
},
{
id: 2,
name: 'Germany',
},
{
id: 3,
name: 'France',
},
];
const cities = [
{
countryId: 1,
cities: [
{
id: 1,
name: 'London',
},
{
id: 2,
name: 'Liverpool',
},
{
id: 3,
name: 'Salisbury'
}
],
},
{
countryId: 2,
cities: [
{
id: 4,
name: 'Berlin',
},
{
id: 5,
name: 'Frankfurt',
},
],
},
{
countryId: 3,
cities: [
{
id: 6,
name: 'Paris',
},
],
},
];
switch (this.props.type) {
case 'countries': {
return countries.map((country) => (
<option
key={country.id.toString()}
value={country.id}
>
{country.name}
</option>
));
}
case 'cities': {
const citiesMap = cities.filter((city) => city.countryId === this.props.countryId);
if (citiesMap && citiesMap[0]) {
const citiesList = citiesMap[0].cities;
if (citiesList) {
return citiesList.map((city) => (
<option
key={city.id.toString()}
value={city.id}
>
{city.name}
</option>
));
}
}
return null;
}
default: return null;
}
}
render() {
return (
<select name={this.props.type} ref={(ref) => this.selectRef = ref} onChange={() => this.props.onChange(this.selectRef.value)}>
{this.renderOptions()}
</select>
);
}
}
ReactDOM.render(<App />, document.querySelector("#app"))
UPDATE
Make your
Formcomponent stateful.Add a state property for
countriesinForm(let it becountryId).Pass this property as a prop into the second
Autocompletecomponent.When the first
Autocompletechanges, change thecountryIdof theForm.
Solution 3:[3]
I've done something similar which may help you.
The Object.keys(instutiontypes) you could use to have an array of countries, instead. Then inside of those values, you can have an array of objects. You could have the cities here, e.g. {value: "Manchester", "label: Manchester", phoneExt: "0114"}
const instutiontypes = {
Kindergarten: [
{ value: "PreK", label: "PreK" },
{ value: "K1", label: "K1" },
{ value: "K2", label: "K2" },
{ value: "K3", label: "K3" },
],
"Primary School": [
{ value: "Grade 1", label: "Grade 1" },
{ value: "Grade 2", label: "Grade 2" },
{ value: "Grade 3", label: "Grade 3" },
{ value: "Grade 4", label: "Grade 4" },
{ value: "Grade 5", label: "Grade 5" },
{ value: "Grade 6", label: "Grade 6" },
],
}
To have the options in my input, I use Object.keys(instutiontypes) to get ['Kindergarten','Primary School']
Then, to get the array of ages to give to my secondary dropdown, I have written this code:
const types = ['Selection1', 'Selection2']
const agesList = [];
for (let i = 0; i < types.length; i++) {
Object.values(institutionTypes[types[i]]).map(({ label }) =>
agesList.push(label)
);
}
This way, the ages dropdown list is dependent on the values passed to institutionTypes.
I'm using mui's <Autocomplete /> components to make them be search dropdowns, with the prop options for the arrays.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | ALazenka |
| Solution 2 | |
| Solution 3 |
