2

According to the MUI Texfield API here, Textfield is a simple abstraction on top of the following components

  1. FormControl
  2. Input
  3. InputLabel
  4. FilledInput
  5. OutlinedInput
  6. Input
  7. FormHelperText

And therefore, to change the styling of the Textfield for any of the components above, like for example notchedOutline class, which is a class for OutlinedInput, i can just do the following

import { TextField } from '@material-ui/core';

const style = theme => ({
  notchOutline: { /*style in here*/ }
});

<TextField
    inputProps={{ notchedOutline : classes.notchedOutline }}
>
</TextField>

All of this can be achieved if that subcomponent classes are unique for that component only.

My question is, how can i style for the more common naming class, like if say i wanna modify the root classes of OutlinedInput, InputLabel, FormHelperText or more subcomponents inside the TextField all at once? I dont think this will work right?

<TextField
    FormControlProps={{ root: classes.root }}
    OutlinedInputProps={{ root: classes.root, notchedOutline : classes.notchedOutline }}
>
</TextField>

or

<TextField
    inputProps={{ 
        root: classes.OutlinedInputRoot, 
        root : classes.FormHelperTextRoot 
    }}
>
</TextField>

Need help on how to aim the specific root of a subcomponent of a TextField, without needing to touch on the global MUI theming, or not using the provided TextField at all, instead building the textfield component using those subcomponents on it.

Fred A
  • 1,602
  • 1
  • 24
  • 41

2 Answers2

3

Below is an example showing how to target each of these.

Targeting TextField root is equivalent to targeting FormControl, since FormControl is the "root" component rendered by TextField.

There is no difference in how to target Input, FilledInput, or OutlinedInput -- they are all reached via InputProps.

As a side note, using the className prop for a given component is also equivalent to classes.root.

import React from "react";
import ReactDOM from "react-dom";

import TextField from "@material-ui/core/TextField";
import { makeStyles } from "@material-ui/core/styles";
const useStyles = makeStyles({
  formControlRoot: {
    border: "2px solid lightgreen",
    padding: 2,
    marginTop: 10
  },
  inputRoot: {
    border: "2px solid blue"
  },
  inputLabelRoot: {
    border: "2px solid pink"
  },
  formHelperTextRoot: {
    border: "2px solid red"
  }
});

function App() {
  const classes = useStyles();
  const [variant, setVariant] = React.useState("standard");
  return (
    <div>
      <TextField
        variant={variant}
        label={`My Label (${variant})`}
        helperText="My Helper Text"
        classes={{ root: classes.formControlRoot }}
        InputProps={{ classes: { root: classes.inputRoot } }}
        InputLabelProps={{ classes: { root: classes.inputLabelRoot } }}
        FormHelperTextProps={{ classes: { root: classes.formHelperTextRoot } }}
      />
      <br />
      <br />
      <button onClick={() => setVariant("standard")}>Standard</button>
      <button onClick={() => setVariant("outlined")}>Outlined</button>
      <button onClick={() => setVariant("filled")}>Filled</button>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Edit TextField component roots

Relevant documentation: https://material-ui.com/api/text-field/#props

Ryan Cogswell
  • 75,046
  • 9
  • 218
  • 198
0

answering this will depend specifically on the material ui version you are using, but i'm going to assume you are using version > 3.

All the following should be working in version 3.9 as i have used them myself, but they are also supposed to work fine with version > 4;

input props are used to pass props to the underlying regular html input element directly, you can pass things like style, max, value, onchange. Things that are native to the html input element.

If you want to pass classes to the underlying material ui input you need to pass a classes object to the InputProps.

Here is how

<TextField    
    variant="outlined"
    // this passes props to the html element, root for example here does not mean anything
    inputProps={{
      style: { textAlign: 'center' },
    }
    // this passes props to the wrapper material input, can be  one of the following: Input, FilledInput, OutlinedInput
    // You can pass here anything that the underlying material component uses but we are only interested in two things classes and className, because other props like value and onChange you can pass directly to TextField - thats why they said TextField is an Abstraction over theses Components
    InputProps={{
       className: styles.slider_filter_input, // usually you dont need className, classes will be sufficient, but wanted to show that you can also use it 
       classes: {
          focused: classes.focused
          // the list of keys you pass here depend on your variant, if for example you used variant="outlined" then you need to check the css api of the OutlinedInput
       }
    }}
/>

Finally here is a working codesandbox showing the ideas above https://codesandbox.io/s/material-ui-drawer-8p6wv

ehab
  • 7,162
  • 1
  • 25
  • 30
  • Thanks. My mistake there writing the property as inputProps instead of InputProps. Assuming if my TextField is an outlined type, and i'm using helper text too, how can i change both component's root? Say like i wanna change the textfield outline's color and helpertext's background color? – Fred A Sep 13 '19 at 09:00