Create a Material-UI Custom Select Component with React js.

In my previous article, I explained How to Integrate the Material-UI with React JS. The article readers through creating and running a React app.

Building Your React.js Application: A Step-by-Step

Step 1. Setting Up The Node Environment.

Ensure that Node.js is installed on your system, as npm requires it to manage packages.

To get started, install Node.js. I have provided a comprehensive guide on setting up Node.js in an article. You can refer to this article, where I explain the process step by step.

"Setting Up the Node Environment and Running a Simple Node Server Project."

Step 2. Create a React Application.

To create a new React app, you can use the create-react-app command-line tool, an officially supported way to create React applications. Here are the steps.

  1. Open your terminal or command prompt.
  2. Run the following command to install create-react-app globally (if you haven't done so before).
    npm install -g create-react-app
  3. Once the installation is complete, create a new React app by running.

    npx create-react-app material-ui-app
  4. Move to the project folder and open the source in vs-code.

Now we have opened the code in vs-code. You can see the file structure and package.json. I removed the unwanted file from the source code.

File structure

Picture 1. You can see the files and folder structure.

Step 3. Install the Material UI.

Go to the Material-UI website and get some instructions.

There are three types of versions in the Material-UI.

  1. V6.0.1 is the new version of MUI-CORE
  2. V5 is the older version of MUI-CORE
  3. The older version is V4 Material-UI-core.

MUI Installation

npm install @mui/material @emotion/react @emotion/styled

MUI Installation

Picture 2. Successfully install. V6.0.1 MUI CORE

Google Web Fonts

To install Roboto via the Google Web Fonts CDN, insert the following code inside the <head> tag of your project.

<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
  rel="stylesheet"
  href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;600;700&display=swap"
/>
  1. Go to the public folder in your project and open the index.html file.
  2. Copy the CDN code and paste it inside the <head> tag of the index.html.

 CDN code

Picture 3. Successfully add Google Web Fonts CDN

Font Icons

To utilize the Font Icon component or the prebuilt SVG Material Icons, you need to install the Material Icons font first. You can achieve this either with npm or through the Google Web Fonts CDN.

npm install @mui/icons-material
<link
  rel="stylesheet"
  href="https://fonts.googleapis.com/icon?family=Material+Icons"
/>

Open the index.html file and paste the CDN code inside the <head> tag of the index.html.

Now we can see the package.json, installed packages added or not.

Installed packages

Picture 4. Installed packages were added in JSON

Now, run the application and check it.

Run the application

Picture 5. Successfully run the application

Step 4. Create the Material UI Custom Select component.

Go to the material-ui-react-select page. I select the basic.

Material UI Custom

Picture 6. See the basics and select

In your project directory, navigate to the src folder and create a new folder named Custom_Component.

Inside the Custom_Component folder, create the CustomBasicSelect .jsx, and define your component using either function.

Create Custom Component

This is my CustomBasicSelect.JSX code.

import React from "react";
import Select from "@mui/material/Select";
import MenuItem from "@mui/material/MenuItem";
import { Box, FormControl, InputLabel } from "@mui/material";

export default function CustomBasicSelect({
  id,
  name,
  title,
  value,
  onChange,
  options = [],
  disabled = false,
  disableUnderline = false,
  inputProps = {},
  errors = {},
  className = "",
}) {
  return (
    <>
      <div>
        <Box sx={{ minWidth: 60 }}>
          <FormControl fullWidth>
            <InputLabel id="demo-simple-select-label">{title}</InputLabel>

            <Select
              id={id}
              name={name}
              aria-label={title}
              inputProps={{
                id: id,
                "aria-labelledby": id,
                ...inputProps,
              }}
              disableUnderline={disableUnderline}
              readOnly={disabled}
              label={title}
              value={value}
              onChange={onChange}
              error={Boolean(errors[name])}
            >
              {options.map((option) => (
                <MenuItem key={option.value} value={option.value}>
                  {option.label}
                </MenuItem>
              ))}
            </Select>
          </FormControl>
        </Box>
      </div>
    </>
  );
}

Component Definition

  • CustomBasicSelect is a functional component that takes several props to customize its behavior. Here’s what each prop is used for,
  • id, name, title: Basic identifiers for the select input and the label.
  • value: The current selected value in the dropdown.
  • onChange A function to handle changes when a different option is selected.
  • options: An array of objects representing the dropdown options, where each object typically has a value and a label.
  • disabled: A boolean to make the dropdown read-only.
  • disableUnderline: A boolean to control the underline style of the select input.
  • inputProps: Additional input properties to be passed to the select input.
  • errors: An object containing any validation errors.
  • className: A string to apply custom CSS classes.

JSX Structure

  • The label element is linked to the Select component by the htmlFor attribute using the id.
  • The Select component renders a dropdown menu using Material-UI. It has various attributes like id, name, aria-label, value, onChange, etc., to control its behavior.
  • options.map() is used to dynamically create MenuItem elements for each option in the options array.
  • The error prop is set using Boolean(errors[name]) to handle error states.

Create an array of Object

I'm going to create a sample country list like this.

[
  { "value": "GB", "label": "United Kingdom" },
  { "value": "US", "label": "United States" },
  { "value": "AR", "label": "Argentina" },
  { "value": "AU", "label": "Australia" },
  { "value": "AT", "label": "Austria" }
  // ...
]

Add custom select in App.js.

import React, { useState } from "react";
import "./App.css";
import CustomBasicSelect from "./Custom_Component/CustomBasicSelect";
import listOfCountry from "./util/ListOfCountries.json";
import Grid from "@mui/material/Grid";
import { Box } from "@mui/material";

function App() {
  const [selectedCountry, setSelectedCountry] = useState("");

  const handleCountryChange = (event) => {
    setSelectedCountry(event.target.value);
  };

  return (
    <div className="App">
      <h1>Material-UI App</h1>
      <h2>Material-UI Custom Select</h2>
      <Box sx={{ flexGrow: 1 }}>
        <Grid container spacing={2}>
          <Grid item xs={12}>
            <CustomBasicSelect
              id="custom-select"
              name="customSelect"
              title="Choose Country"
              value={selectedCountry}
              onChange={handleCountryChange}
              options={listOfCountry}
              errors={{
                customSelect:
                  selectedCountry === "" ? "Please select a country" : "",
              }}
              // className="custom-select-class"
            />
          </Grid>

          <h2>
            <div style={{ background: "#81c784" }}>{selectedCountry}</div>
          </h2>
        </Grid>
      </Box>
    </div>
  );
}

export default App;

Explanation of the Code

  1. Imports
    • CustomBasicSelect: A custom select component imported from another file (Custom_Component/CustomBasicSelect). This is the dropdown component that you provided earlier.
    • listOfCountry: A JSON file (ListOfCountries.json) imported from the ./util directory that contains a list of country options for the select component.
  2. Function Component: App
  3. State Management
    • selectedCountry: A state variable initialized to an empty string (""). It keeps track of the currently selected country in the dropdown.
    • setSelectedCountry: A function provided by useState to update the selected country state whenever a new option is selected.
  4. Handler Function
    • handleCountryChange: A function that is called whenever the user selects a different country. It takes an event object as a parameter and updates the selected country state with the value of the selected option (event.target.value).
  5. JSX Structure
    • Material-UI Box Component
      • Used to create a flex container (sx={{ flexGrow: 1 }}) to wrap the content.
    • Material-UI Grid Component
      • Used for layout purposes, creating a grid system with a container that has a spacing of 2 units.
      • Inside the grid, a Grid item is defined with a size of 4 (out of 12, as Material-UI grids are based on a 12-column layout by default).
    • CustomBasicSelect Component
      • The custom select component is used to display a dropdown list of countries.
      • Several props are passed to customize the component:
        • id, name, title: Identifiers and a label for the select input.
        • value: The currently selected country (selected country).
        • onChange: The handler function (handleCountryChange) to manage changes in the selected country.
        • options: The list of countries (listOfCountry) from the JSON file.
        • errors: An object that contains an error message if no country is selected.

Error message

Picture 7. Basics Select

Sample country list

Picture 8. See the sample country list

When you select the country fair on the onChange event, call the handleCountryChange function and update the states setSelectedCountry(event.target.value);

I add a piece of code.

<h2>
  <div style={{ background: "#81c784" }}>
    {selectedCountry}
  </div>
</h2>

When selecting, the values will be displayed.

Values

Picture 9. You can see the selected value in the highlight

Conclusion

In this article, we have successfully built a custom select component in a React application using Material-UI. By setting up a new React environment, integrating Material-UI, and creating reusable components like CustomBasicSelect, we demonstrated how to efficiently manage form inputs and state. This approach can be extended to create more sophisticated form elements, enhancing the user experience in your React applications.


Orfium Sri Lanka
Globally based Software Developing & Data Processing Company