How to create a Multiform in Material UI and Next Js
MUINext Js|

Ayush

Arya

|

Jan 28, 24

How To Create A Multiform In MUI And Next Js?

Embarking on the journey of creating a Multiform with Material-UI and Next.js opens the door to a world of possibilities for dynamic and engaging user experiences. In this comprehensive guide, we’ll explore the intricacies of building a Multiform and dive into the provided code snippets step by step.

Unveiling the Multiform Architecture

Multiform Component – MultiForms.js

Now, let’s delve into the MultiForms component, where Material-UI’s Stepper guides users through different steps. The showSteps function dynamically renders the appropriate form step based on the current step.

// MultiForms.js
import React, { useContext } from "react";
import StepOne from "./StepOne";
import StepTwo from "./StepTwo";
import { Stepper, StepLabel, Step } from "@mui/material";
import { MultiStepContext } from "./StepContext";

const MultiForms = () => {
  const { currentstep } = useContext(MultiStepContext);

  function showSteps(step) {
    switch (step) {
      case 1:
        return <StepOne />;
      case 2:
        return <StepTwo />;
      default:
        // Handle additional steps as needed
    }
  }

  return (
    <>
      <div className="App">
        <center>
          <h1> MultiForms</h1>
          <Stepper
            style={{ width: "400px" }}
            activeStep={currentstep - 1}
            orientation="horizontal"
          >
            <Step>
              <StepLabel></StepLabel>
            </Step>
            <Step>
              <StepLabel></StepLabel>
            </Step>
          </Stepper>
          {showSteps(currentstep)}
        </center>
      </div>
    </>
  );
};

export default MultiForms;

Step Context – StepContext.js

The StepContext component plays a pivotal role in managing the state of the Multiform. It handles form data, form errors, the current step, and provides functions like SubmitData to process the collected information.

// StepContext.js
import React, { useState } from "react";
import MultiForms from "./MultiForms";

export const MultiStepContext = React.createContext();
const StepContext = () => {
  const [currentstep, setCurrentStep] = useState(1);
  const [UserData, setUserData] = useState({
    firstname: "",
    lastname: "",
    email: "",
    number: "",
    address: "",
    city: "",
  });
  const [File, setFile] = useState("");
  const [formErrors, setFormError] = useState({});

  function SubmitData() {
    console.log("click");
    let Data = { UserData, File };
    console.log(Data);
    // Further processing logic can be added here
  }

  return (
    <>
      <div>
        <MultiStepContext.Provider
          value={{
            formErrors,
            setFormError,
            File,
            setFile,
            currentstep,
            setCurrentStep,
            UserData,
            setUserData,
            SubmitData,
          }}
        >
          <MultiForms />
        </MultiStepContext.Provider>
      </div>
    </>
  );
};

export default StepContext;

app.js – The Gateway to Multiforms

Let’s start by understanding the root _app.js file. This file initializes the application and wraps it with a StepContext component, a crucial part of our Multiform architecture. The StepContext will manage the flow between different form steps.

// _app.js
import StepContext from "@/components/MultiForm/StepContext";
import "@/styles/globals.css";

export default function App({ Component, pageProps }) {
  return (
    <>
      <StepContext>
        <Component {...pageProps} />;
      </StepContext>
    </>
  );
}

StepOne – Collecting Basic Information

StepOne.js handles the collection of basic user information, ensuring that all required fields are filled. Validation logic is implemented to display errors if necessary.

// StepOne.js
import React, { useContext } from "react";
import { Button, TextField } from "@mui/material";
import { MultiStepContext } from "./StepContext";

const StepOne = () => {
  const { setCurrentStep, UserData, setUserData, formErrors, setFormError } =
    useContext(MultiStepContext);

  const handleInput = (e) => {
    setUserData({ ...UserData, [e.target.name]: e.target.value });
  };

  const validate = () => {
    let inputValid = UserData;
    let formErrors = {};
    let isValid = true;
    const reg = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i;

    if (!inputValid.firstname) {
      isValid = false;
      formErrors.firstname = "Firstname field is required!";
    }
    if (!inputValid.lastname) {
      isValid = false;
      formErrors.lastname = "Lastname field is required!";
    }
    if (!inputValid.email) {
      isValid = false;
      formErrors.email = "Email field is required ";
    } else if (!reg.test(inputValid.email)) {
      isValid = false;
      formErrors.email = "This is not a valid email";
    }
    setFormError(formErrors);
    return isValid;
  };

  const stepButtonTwo = (e) => {
    e.preventDefault();
    if (validate()) {
      setCurrentStep(2);
    }
  };
  return (
    <>
      <div className="container">
        <div>
          <TextField
            className="wd"
            type="text"
            value={UserData.firstname}
            name="firstname"
            onChange={handleInput}
            label="FirstName"
            margin="normal"
            variant="outlined"
            color="primary"
          />
        </div>
        <span style={{ color: "red" }}>{formErrors.firstname}</span>
        <div>
          <TextField
            className="wd"
            type="text"
            value={UserData.lastname}
            name="lastname"
            onChange={handleInput}
            label="LastName"
            margin="normal"
            variant="outlined"
            color="primary"
          />
        </div>
        <span style={{ color: "red" }}>{formErrors.lastname}</span>
        <div>
          <TextField
            className="wd"
            type="email"
            value={UserData.email}
            name="email"
            onChange={handleInput}
            label="Email"
            margin="normal"
            variant="outlined"
            color="primary"
          />
        </div>
        <span style={{ color: "red" }}>{formErrors.email}</span>
        <div>
          <Button
            style={{ margin: "10px" }}
            variant="contained"
            onClick={stepButtonTwo}
            color="primary"
          >
            Next
          </Button>
        </div>
      </div>
    </>
  );
};

export default StepOne;

StepTwo – Advanced Information and File Upload

StepTwo.js focuses on collecting advanced user information and allows users to upload a file. Similar to StepOne, it includes validation logic for error handling.

// StepTwo.js
import React, { useContext } from "react";
import {
  Button,
  TextField,
  Select,
  FormControl,
  MenuItem,
  InputLabel,
} from "@mui/material";
import { MultiStepContext } from "./StepContext";
import FileUploadIcon from "@mui/icons-material/FileUpload";

const StepTwo = () => {
  const {
    setCurrentStep,
    UserData,
    setUserData,
    SubmitData,
    File,
    setFile,
    formErrors,
    setFormError,
  } = useContext(MultiStepContext);

  const validate = () => {
    let inputValid = UserData;
    let formErrors = {};
    let isValid = true;

    if (!inputValid.address) {
      isValid = false;
      formErrors.address = "Address field is required!";
    }
    if (!inputValid.city) {
      isValid = false;
      formErrors.city = "City field is required!";
    }
    if (!inputValid.number) {
      isValid = false;
      formErrors.number = "Number field is required!";
    } else if (inputValid.number.length !== 10) {
      isValid = false;
      formErrors.number = "Number must be 10 characters";
    }
    if (!File) {
      isValid = false;
      formErrors.File = "File field is required!";
    }
    setFormError(formErrors);
    return isValid;
  };

  const stepButtonFinal = (e) => {
    e.preventDefault();
    if (validate()) {
      SubmitData();
    }
  };

  const handleInput = (e) => {
    setUserData({ ...UserData, [e.target.name]: e.target.value });
  };

  const handleFile = (e) => {
    const file = e.target.files[0];
    setFile(file);
    console.log(file);
  };
  return (
    <div className="container">
      <div>
        <TextField
          className="wd"
          type="number"
          value={UserData.number}
          onChange={handleInput}
          name="number"
          label="Number"
          margin="normal"
          variant="outlined"
          color="primary"
        />
      </div>
      <span style={{ color: "red" }}>{formErrors.number}</span>

      <div>
        <TextField
          className="wd"
          type="text"
          value={UserData.address}
          name="address"
          onChange={handleInput}
          label="Address"
          margin="normal"
          variant="outlined"
          color="primary"
        />
      </div>
      <span style={{ color: "red" }}>{formErrors.address}</span>

      <div>
        <FormControl sx={{ my: 2, minWidth: 220 }}>
          <InputLabel id="demo-simple-select-label">Enter City</InputLabel>
          <Select
            labelId="demo-simple-select-label"
            id="demo-simple-select"
            value={UserData.city}
            name="city"
            label="Enter City"
            onChange={handleInput}
          >
            <MenuItem value="london">London</MenuItem>
            <MenuItem value="newyork">New york</MenuItem>
            <MenuItem value="dubai">Dubai</MenuItem>
          </Select>
        </FormControl>
      </div>
      <span style={{ color: "red" }}>{formErrors.city}</span>

      <div className="f-file">
        <input
          onChange={handleFile}
          name="file"
          type="file"
          accept=""
          style={{ display: "none" }}
          id="contained-button-file"
          multiple
        />
        <label htmlFor="contained-button-file">
          <Button variant="contained" color="primary" component="span">
            <FileUploadIcon />
            Upload
          </Button>
        </label>
        <div>{File.name}</div>
      </div>
      <span style={{ color: "red" }}>{formErrors.File}</span>

      <div>
        <Button
          variant="contained"
          onClick={() => setCurrentStep(1)}
          color="secondary"
        >
          Back
        </Button>
        <span> </span>
        <Button
          style={{ margin: "10px" }}
          variant="contained"
          onClick={stepButtonFinal}
          color="primary"
        >
          Submit
        </Button>
      </div>
    </div>
  );
};

export default StepTwo;

Conclusion: Crafting a Seamless Multiform Experience

In conclusion, mastering the art of Multiforms with Material-UI and Next.js empowers you to create interactive, step-by-step user journeys. By understanding the provided code snippets, you have the foundation to customize and expand this Multiform for your specific project needs.

Enhance your development skills with more insights and tutorials at Your Learning Hub.


Popular Blog Categories


Contact Me

Phone

Discuss A Project Or Just Want To Say Hi?
My Inbox Is Open For All.

Mail : techayu001@gmail.com

Chatbot