bigBadWolf
bigBadWolf

Reputation: 100

Conditionally display input field

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

Answers (4)

M.Calugaru
M.Calugaru

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:

  1. MenuForm - this can be your main menu form component;
  2. MenuItem - this is a component that generates selection options for a menu item
  3. Crete additional components to handle the specifics of each menu item, say PizzaItemMenu, SoupItemMenu, etc.

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

ishan avishka
ishan avishka

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

John Lobo
John Lobo

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

John
John

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

Related Questions