Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React - Dynamic form fields where fields change based on a dropdown menu (using hooks)

Tags:

I have a form in which I would like to render different fields based on a category which is selected from a dropdown. For instance in the following example, if there are categories named 'phones' and 'laptops, if 'laptops' is selected the form will include the field 'network' and if laptops' is selected, the form will include the field 'processor' (both are currently shown). What is the best way to go about doing this? I assume I would need to store the selected dropdown option in state and render the fields based on that, but I'm at a loss as to how to accomplish it without breaking what I currently have.

import React, { useState, useEffect } from "react";
import Layout from "../core/Layout";
import { isAuthenticated } from "../auth";
import { createProduct, getCategories } from './apiAdmin';

const AddProduct = () => {
  const [values, setValues] = useState({
    name: '', network: '',  processor: '', categories: [], category: '', loading: false, error: '', createdProduct: '', redirectToProfile: false, formData: ''
  });
  const { user, token } = isAuthenticated();
  const { name, network, processor, categories, category, loading, error, createdProduct, redirectToProfile, formData } = values;

  const init = () => {
    getCategories().then(data => {
      if (data.error) {
        setValues({ ...values, error: data.error });
      } 
      else {
        setValues({...values, categories: data, formData: new FormData() });
      }
    });
  };

  useEffect(() => {
    init();
  }, []);

  const handleChange = name => event => {
    const value = event.target.value;
    formData.set(name, value);
    setValues({ ...values, [name]: value });
  };

  const clickSubmit = (event) => {
    event.preventDefault();
    setValues({ ...values, error: '', loading: true });
    createProduct(user._id, token, formData)
      .then(data => {
        if (data.error) {
          setValues({ ...values, error: data.error });
        }
        else {
          setValues({ ...values, name: '', network: '', processor: '', loading: false, createdProduct: data.model });
        }
      });
  };

  const newPostForm = () => (
    <form className='mb-3' onSubmit={clickSubmit} >
      <div className='form-group'>
        <label className='text-muted'>Category</label>
        <select onChange={handleChange('category')} className='form-control'>
          <option>Select a Category</option>
          { categories && categories.map((c, i) => (<option key={i} value={c._id}>{c.name}</option>)) }
        </select> 
      </div>    
      <div className='form-group'>
        <label className='text-muted'>Name</label>
        <input 
          onChange={handleChange('name') } 
          type='text' 
          className='form-control' 
          value={name} 
        /> 
      </div>    

      // *****************************************************************************************
      // ************  THIS SHOULD BE RENDERED ONLY IF CATEGORY 'PHONES' IS SELECTED  ************
      // *****************************************************************************************

      <div className='form-group'>
        <label className='text-muted'>Network</label>
        <input 
          onChange={handleChange('network') } 
          type='text' 
          className='form-control' 
          value={network} 
        /> 
      </div>

      // *****************************************************************************************
      // ***********  THIS SHOULD BE RENDERED ONLY IF CATEGORY 'LAPTOPS' IS SELECTED  ************
      // *****************************************************************************************
      <div className='form-group'>
        <label className='text-muted'>Processor</label>
        <input 
          onChange={handleChange('processor') } 
          type='text' 
          className='form-control' 
          value={processor} 
        /> 
      </div>
      <button className='btn btn-outline-primary'>
        Submit
      </button>
    </form>
  );

  return (
    <Layout title='Add Product' description={`Welcome, ${user.name}.`} >
      <div className='row'>
        <div className='col-md-8 offset-md-2'>
          {newPostForm()}
        </div>
      </div>
    </Layout>
  )
}

export default AddProduct;
like image 356
mattC Avatar asked Dec 30 '19 16:12

mattC


2 Answers

This will help you.

formData.get("category") === "phones" ? <> PHONES DISPLAY DIV </> : formData.get("category") === "laptops" ? <> LAPTOPS DISPLAY DIV</> : null

like image 128
praval Avatar answered Oct 12 '22 21:10

praval


This should work for you:

const newPostForm = () => (

  return <form>

    { category === 'phones' && <div> YOUR PHONES FIELDS HERE </div> }

    { category === 'laptops' && <div> YOUR LAPTOP FIELDS HERE </div }

  </form>

);
like image 23
Joshua Beckers Avatar answered Oct 12 '22 22:10

Joshua Beckers