How to customize TextField error color in Material-UI using conditional logic in React

Currently, I am incorporating the React Material-UI library into my project and faced with a challenge of conditionally changing the error color of a TextField.

My goal is to alter the color of the helper text, border, text, and required marker to yellow in case of a specific type of error. Here is a visual representation of what I aim to achieve:

For other types of errors, I would like to maintain the default red color. Even though I attempted to follow the method used in this codesandbox, I found it challenging to identify all the components that needed modification. Consequently, I had to resort to using the "important" keyword extensively to notice any changes.

Fortunately, I did succeed in selectively altering the color of the helper text as shown below:

                        <TextField
                            label="Name"
                            className={formClasses.textField}
                            margin="normal"
                            variant="outlined"
                            required
                            error={!!errors}
                            helperText={errors && "Incorrect entry."}
                            FormHelperTextProps={{classes: {root: getColorType(AnErrorType)}}}
                        />

The function getColorType is designed to return a CSS object specifying the desired color based on the given error type. For instance, the following snippet demonstrates how it determines the color for hard required hint text:

hardRequiredHintText: {
    color: `${theme.palette.warning.light} !important`
},

In conclusion, I wonder if there exists a simpler approach to override the MUI error color consistently across all relevant components?

Answer №1

To indicate different types of validation with distinct colors, we have the ability to send parameters to makeStyles

import { makeStyles } from "@material-ui/core/styles";
const useStyles = params =>
  makeStyles(theme => ({
    root: {
    }
  }));
const Component = () => {
  const classes = useStyles(someParams)();


Complete code:

import React from "react";
import "./styles.css";
import { TextField } from "@material-ui/core";
import { makeStyles } from "@material-ui/core/styles";
const useStyles = value =>
  makeStyles(theme => ({
    root: {
      "& .Mui-error": {
        color: acquireValidationColor(value)
      },
      "& .MuiFormHelperText-root": {
        color: acquireValidationColor(value)
      }
    }
  }));

const acquireValidationColor = message => {
  switch (message) {
    case "Incorrect entry":
      return "green";
    case "Please input":
      return "orange";
    default:
      return "black";
  }
};

const ValidationTextField = ({ helperText }) => {
  const classes = useStyles(helperText)();
  return (
    <TextField
      label="Name"
      margin="normal"
      variant="outlined"
      required
      error={helperText !== ""}
      helperText={helperText}
      className={classes.root}
    />
  );
};

export default function App() {
  const data = ["Incorrect entry", "Please input", ""];
  return (
    <div className="App">
      {data.map((x, idx) => (
        <ValidationTextField helperText={x} key={idx} />
      ))}
    </div>
  );
}

Answer №2

For Class Based Components

import React from "react";
import { TextField } from "@material-ui/core";
import { withStyles, createStyles } from "@material-ui/core/styles";

const commonStyles = (theme) =>
  createStyles({
    root: {},

    warningStyles: {
      "& .MuiFormLabel-root.Mui-error": {
        color: "orange !important"
      },
      "& .MuiInput-underline.Mui-error:after": {
        borderBottomColor: "orange !important"
      },
      "& .MuiFormHelperText-root.Mui-error": {
        color: "orange !important"
      }
    }
  });

class DemoComponent extends React.Component {
  render() {
    const { classes } = this.props;
    const _text1HasWarning = false;
    const _text2HasWarning = true;
    const _text3HasWarning = false;

    return (
      <>
        <TextField
          error={false}
          className={_text1HasWarning ? classes.warningStyles : null}
          value="Valid Value"
          variant="standard"
          label="Valid label"
          helperText="Valid helper text"
        />
        <br />
        <br />
        <br />
        <TextField
          error={true}
          className={_text2HasWarning ? classes.warningStyles : null}
          value="warning value"
          variant="standard"
          label="warning label"
          helperText="warning helper text"
        />
        <br />
        <br />
        <br />
        <TextField
          error={true}
          className={_text3HasWarning ? classes.warningStyles : null}
          value="error value"
          variant="standard"
          helperText="error helper text"
          label="error label"
        />
      </>
    );
  }
}
export default withStyles(commonStyles)(DemoComponent);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Output

Answer №3

To achieve this, you can customize your Material-UI theme's default styles by overriding them and then encapsulating your text field or component within myTheme

import { createMuiTheme } from 'material-ui/styles';
 const myTheme = createMuiTheme({
 overrides:{
    MuiInput: {
        underline: {
                '&:after': {
                  backgroundColor: 'any_color_value_in_hex',
                }
             },
          },
       }
   });
   export default myTheme;

Afterwards, import it into your component and use:

import {MuiThemeProvider} from 'material-ui/styles';
import myTheme from './components/myTheme'

<MuiThemeProvider theme = {myTheme}>
  <TextField />
</MuiThemeProvider>

Hopefully this explanation is helpful to you.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Exploring the implementation of a many-to-many relationship on a webpage

In the process of creating a library database and dealing with a many-to-many relationship between books and writers, I am contemplating how best to design the user interface for managing this information. When editing a book entry, selecting one or more ...

Guidelines for iterating through a nested JSON array and extracting a search query in Angular

I'm currently working with a complex nested JSON Array and I need to filter it (based on the name property) according to what the user enters in an input tag, displaying the results as an autocomplete. I've started developing a basic version of t ...

Is it possible to adjust the position of my React button using numerical values (##px) without success?

I'm facing an issue with positioning my button to the right. Despite my best efforts, I haven't been able to move it more than a few positions. In summary, here are the scenarios I've encountered while trying to solve this problem: When I ...

Is it possible to declare variables using the "this" keyword?

Consider the scenario where this.x=5 is declared and assess the accessibility of all relevant places. <script> $(document).ready(function(){ $("button").click(function(){ this.x=!this.x; $("#div1").fadeTo(400,this.x ? 0.4 : 1); }); }); & ...

React - Children components in an array not updating when props are modified within a callback function

The question may be a bit unclear, so let me provide further explanation. This is a personal project I am working on to improve my understanding of React basics and socket.io. Within this project, I have developed a CollapsibleList component and a NestedL ...

My experience with jquery addClass and removeClass functions has not been as smooth as I had hoped

I have a series of tables each separated by div tags. Whenever a user clicks on a letter, I want to display only the relevant div tag contents. This can be achieved using the following jQuery code: $(".expand_button").on("click", function() { $(th ...

Transforming an Excel document into JSON format: inspection of JSON code structure

Looking to transform Excel data into JSON format, but unsure if the current structure will be ideal for processing with D3.js. Planning to incorporate this JSON file within D3.js for visualization purposes. Here's a snippet of the Excel file: In the ...

What's the reason for the element not inheriting margins from its parent?

I am facing an issue with centering an h1 header within a .banner element. When I try to apply margin to the header, it appears to indent not from the top border of the banner, but rather from the nav element located above the banner. After inspecting the ...

The modal appears on the screen prior to the content being shown

While attempting to render a bootstrap modal with content from a REST call, I am encountering an issue where the modal appears before the content has finished populating. The modal is triggered by a button click event. If I click the button again after wa ...

Design a progress bar that advances in increments of at least two and up to a maximum of

My task involves managing a simple list. const [progressBar, setProgressBar] = useState([ { isActive: false, name: "step1" }, { isActive: false, name: "step2" }, { isActive: false, name: "step3" }, { isActive ...

Using the IE method getelementbyid to target an object within the document

Is there a way to use getElementById to access an object that already exists in the document? I am specifically trying to target the element "test" which is nested within parentDiv1. While this code works in Firefox, it's not functioning properly ...

The OutlinedInput component from Material-UI seems to be struggling to display the startAdornment

Below is the code snippet. The start adornment is not displaying in the textfield, and there is no text appearing on the label. <InputLabel>Mobile Number</InputLabel> <OutlinedInput variant="outlined" ...

Adjusted position of the viewport if the DOM element containing the renderer is not located at the top of the display

I've come across an issue with a three.js scene within an Angular custom directive in the view. At the top, there's a navigation bar for switching between views (pretty standard so far). I set up a simple scene with a cube and basic camera rotati ...

Troubleshooting my Xpath query for HTML - where did I make a mistake?

Within the <BODY> tags, there is a piece of HTML that I'm attempting to target using scrapy: <section class="content"> <div class="social clearfix"> <div class="profile profile-nano pull-left"> <a hr ...

Changing the format of a numerical value to include commas for every 1000 increment

I'm trying to find a way to format numbers in a specific manner, such as changing 1234567 into 1,234,567. However, I've run into some issues when attempting to use the currency pipe of TypeScript. It adds USD or $ in front of the number, which i ...

Detecting Android devices

Issue: My website functions properly on desktop but has a problem with the carousel images skewing on iPhones. To address this, I created a separate CSS styling for iPhone devices and used a JavaScript function found online to detect iPhones and iPads. Un ...

CSS can be utilized to craft intricate and dynamic shapes

Currently, I am attempting to produce a trapeze-like design utilizing various techniques in order to achieve the best possible outcome. The shape I am aiming to create is similar to this: (the content inside the shape will consist of images and text) Th ...

Encountered an i18n NextJS error: The FS Module is not found and cannot resolve 'fs' within a specific component

Hello everyone, this is my first time asking a question here so please bear with me if I make any mistakes in formatting or anything else. I'm here to learn. I have a query regarding running code from index.js for translation purposes: import React fr ...

Issue with Component not displaying properly upon refreshing

I'm currently using react.js and I have a button with an onClick event. My goal is to reload the page after clicking the button and then display a specific component on the page. However, I've encountered an issue where the component doesn't ...

Angular JS: Extracting the header from a CSV file

Just getting started with angular JS and I have a question. I need to take a CSV file from the user as input and then send it to the controller when they click submit. <button class="btn btn-primary" type="submit" ng-click="Input(File)">Submit</ ...