Reputation: 100
I am working on form in react. After selecting dish type I want to conditionally display other fields. For example if I select pizza I want to display number field. If I select soup I want to display other input field.
Here is sample of code:
const Form = () => {
const [dishes] = React.useState([
{
label: "Pizza",
value: "Pizza",
},
{ label: "Soup", value: "Soup" },
{ label: "Sandwich", value: "Sandwich" },
]);
return (
<div>
<form>
<label>Name</label>
<input type="text" required></input>
<label>Preperation Time</label>
<input type="time" step="2" required></input>
<label>Type</label>
<select>
{dishes.map((dish) => (
<option key={dish.value} value={dish.value}>
{dish.label}
</option>
))}
</select>
<button>submit</button>
</form>
</div>
);
};
export default Form;
Upvotes: 0
Views: 2385
Reputation: 442
This is the architecture I would follow (see below). First define your menu, which I presume is not changing so should just be a plain object. Then split you code in a few components:
Here is a full example app in action based on your code:
const menu = {
pizza: {
type: [
{
label: 'neapolitana',
value: 'npa'
}, {
label: 'chicago',
value: 'ccg'
}, {
label: '4-cheese',
value: 'cse'
}],
number: 1,
addOn: false
},
soup: {
type: [{
label: 'carrot',
value: 'crt'
}, {
label: 'potato',
value: 'ptt'
}],
number: 1,
addOn: false
}
}
const MenuForm = () => {
const [menuItem, setMenuItem] = React.useState(false);
const handleMenuItemSelection = (e) => {
setMenuItem(e.target.value);
}
const additionalMenuItemSelections = () => {
switch (menuItem) {
case 'pizza':
return <PizzaItemMenu />
case 'soup':
return <SoupItemMenu />
default:
return false;
}
}
return (
<div>
<form>
<label>Name</label>
<input type="text" required></input>
<label>Preperation Time</label>
<input type="time" step="2" required></input>
<label>Type</label>
<select className='menu' onChange={handleMenuItemSelection} defaultValue='x'>
<option disabled value="x">Select menu item</option>
{Object.keys(menu).map((item, index) => {
return (
<option key={index} value={item}>{item}</option>
)
})}
</select>
{additionalMenuItemSelections()}
<button>submit</button>
</form>
</div>
);
};
const PizzaItemMenu = () => {
const [pizzaType, setPizzaType] = React.useState(false);
const handleSelection = (e) => {
const data = e.target.value;
setPizzaType(data);
}
return (
<div className='soup-menu'>
<p>You've selected pizza!</p>
<MenuItem menuItem='pizza' handleSelection={handleSelection} />
Additional form menu selection options for pizzas goes here
{pizzaType && <p>You've selected {pizzaType} pizza!</p>}
</div>
)
}
const SoupItemMenu = () => {
const [soupType, setSoupType] = React.useState(false);
const handleSelection = (e) => {
const data = e.target.value;
setSoupType(data);
}
return (
<div className='soup-menu'>
<p>You've selected soup!</p>
<MenuItem menuItem='soup' handleSelection={handleSelection} />
Additional form menu selection options for soups goes here
{soupType && (<p>You've selected {soupType} soup!</p>)}
</div>
)
}
const MenuItem = ({ menuItem, handleSelection }) => {
const itemOptions = menu[menuItem].type;
return (
<select id={menuItem} defaultValue='x' onChange={(e) => handleSelection(e)} >
<option disabled value="x">Select {menuItem} type</option>
{itemOptions.map((itemKey, index) => (
<option key={index} value={itemKey.value}>{itemKey.label}</option>
))}
</select>
)
}
export default MenuForm;
Upvotes: 0
Reputation: 75
So you wanna display some JSX on condition right? you can just check the condition and select a output as if condition
<div>
{dishes.value.equals("pizza") && (<input type="number">)}
{dishes.value.equals("soup") && (<input type="text">)}
</div>
You can use Ternary operation to if else condition
<div>
{dishes.value.equals("pizza") ? (<input type="number">) : (<input type="text">)}
</div>
Upvotes: 0
Reputation: 15319
import React, { useState } from 'react';
function App() {
const [dishes] = React.useState([
{
label: "Pizza",
value: "Pizza",
},
{ label: "Soup", value: "Soup" },
{ label: "Sandwich", value: "Sandwich" },
]);
const [type, setType] = useState([])
const handleChang = (value) => {
setType(value);
}
return (
<div>
<form>
{(type == "Pizza") && (<> <label>Name</label>
<input type="text" required></input></>)
}
{(type == "Soup") && (<> <label>Preperation Time</label>
<input type="time" step="2" required></input></>)
}
<label>Type</label>
<select onChange={(e) => handleChang(e.target.value)}>
{dishes.map((dish) => (
<option key={dish.value} value={dish.value}>
{dish.label}
</option>
))}
</select>
<button>submit</button>
</form>
</div>
);
}
export default App;
Upvotes: 1
Reputation: 451
Try this (codesandbox: https://codesandbox.io/s/vigilant-kepler-5xuio?file=/src/App.js)
const [dishes] = React.useState([
{
label: "Pizza",
value: "Pizza",
field: (
<div>
<label htmlFor="pizza">Toppings</label>
<input type="number" id="pizza" />
</div>
)
},
{
label: "Soup",
value: "Soup",
field: (
<div>
<label htmlFor="soup">How soupy?</label>
<input type="range" id="soup" />
</div>
)
},
{
label: "Sandwich",
value: "Sandwich",
field: (
<div>
<label htmlFor="sandwich">Enter your ingredients</label>
<input type="text" id="sandwich" />
</div>
)
}
]);
const [selectedDish, setSelectedDish] = React.useState(dishes[0]);
const handleDishSelect = (e) => {
const dish = dishes.find((dish) => dish.value === e.target.value);
if (dish) {
setSelectedDish(dish);
}
};
return (
<div>
<form>
<label>Name</label>
<input type="text" required></input>
<label>Preperation Time</label>
<input type="time" step="2" required></input>
<label>Type</label>
<select onChange={handleDishSelect}>
{dishes.map((dish) => (
<option key={dish.value} value={dish.value}>
{dish.label}
</option>
))}
</select>
{selectedDish && selectedDish.field}
<button>submit</button>
</form>
</div>
);
Upvotes: 1