How Do I Refactor Common React Components? - reactjs

I am styling a required TextField like this
const styles = theme => ({
labelAsterisk: {
color: "red"
},
cssLabel: {
color: "orange"
},
cssRequired: {
"&:before": {
borderBottom: "2px solid orange"
}
},
});
<TextField
id="requiredField"
label="Required Field"
value="Custom Text"
required
InputLabelProps={{
classes: {
root: classes.cssLabel
},
FormLabelClasses: {
asterisk: classes.labelAsterisk
}
}}
InputProps={{
classes: {
underline: classes.cssRequired
}
}}
margin="normal"
/>
I have lots of these required fields in my forms and would like to standardise it instead of copying and pasting large chunks of code.
What is the best way refactor this so that I only need to specify id, label and value each time I use it?
Do I extend TextField?
Create a new component that extends React.Component?
Use a function or a constant?

Here's how you would define your custom TextField component:
const RequiredTextField = ({id, label, value}) => (
<TextField
id={id}
label={label}
value={value}
required
InputLabelProps={{
classes: {
root: classes.cssLabel
},
FormLabelClasses: {
asterisk: classes.labelAsterisk
}
}}
InputProps={{
classes: {
underline: classes.cssRequired
}
}}
margin="normal"
/>
)
And here's how you would use it:
<RequiredTextField id="some-id" label="some-label" value="some-value">

Related

How to customize label color of material ui Textfield when out of focus?

I'm trying to customize Textfiled of material-ui
I was able to change everything I wanted except the color of the label when out of focus
Here image of my problem
by defualt the color is black (when out of focus)
How could I change that?
here is my code:
const useStyles = makeStyles({
notchedOutline: {
color: "red !important", // label foucus color
borderWidth: "1px",
borderColor: "red !important" // border color when out of focus
},
cssOutlinedInput: {
color: "green !important", // text color when out of focus
"&$cssFocused $notchedOutline": {
borderColor: `yellow !important` // border color when Focused
}
},
cssFocused: {
color: "red !important" // text and label color when focued
},
});
<TextField
id="outlined-basic"
label="Username"
variant="outlined"
type="text"
name="username"
error={usernameError.isInvalid ? true : false}
helperText={usernameError.errorHelper}
onChange={e => setUser({ ...user, username: e.target.value })}
InputLabelProps={{
classes: {
root: classes.cssLabel,
focused: classes.cssFocused
}
}}
InputProps={{
classes: {
root: classes.cssOutlinedInput,
focused: classes.cssFocused,
notchedOutline: classes.notchedOutline
},
startAdornment: (
<InputAdornment position="start">
<AccountCircleSharpIcon />
</InputAdornment>
),
}}
/>
I think you already selecting the correct class root: classes.cssLabel in InputLabelProps, but your shared styles doesn't have the styles for it.
InputLabelProps={{
classes: {
root: classes.cssLabel,
focused: classes.cssFocused
}
}}
Adding below in the makeStyles should fix the problem.
cssLabel: {
color: "red"
}

how to change the asterisk color in required * field

I have two required fields in my form .I want the asterisk color should be red.Currently it is showing black .I am using material UI react library ?
here is my code
https://codesandbox.io/s/r7lq1jnjl4
documents
https://material-ui.com/demos/text-fields/
<FormControl>
<TextField
required
InputLabelProps={{
shrink: true
}}
id="standard-name"
label="Name"
margin="normal"
helperText="Some important text"
/>
</FormControl>
Based on this documentation on how to customize components through theme overrides for a FormLabel (which will also include InputLabel), you should use createMuiTheme and add the following overrides:
const formLabelsTheme = createMuiTheme({
overrides: {
MuiFormLabel: {
asterisk: {
color: '#db3131',
'&$error': {
color: '#db3131'
},
}
}
}
})
Then, you wrap your <form> within a <MuiThemeProvider> like so:
<MuiThemeProvider theme={formLabelsTheme}>
<form noValidate autoComplete="off">
...
...
...
</form>
</MuiThemeProvider>
Here is a forked code sandbox which demonstrates this code in action.
Since you are already creating a theme, you could just put your overrides in that theme, but you'll need to move your <form> to be within the <MuiThemeProvider> that you already have in your code.
The resulting form labels look like this:
As per the latest version of material UI. ie. "#mui/material": "^5.0.1"
We can do it like this:
<FormLabel required>Name:</FormLabel>
And in the theme:
import { createTheme } from "#mui/material";
export const theme = createTheme({
components: {
MuiFormLabel: {
styleOverrides: {
asterisk: {
color: "#db3131",
"&$error": {
color: "#db3131",
},
},
},
},
},
});
In Mui v5 :
const theme = createTheme({
components: {
MuiFormLabel: {
styleOverrides: {
asterisk: {color:"red"},
},
},
},
})
Alvin's answer shows how to do this globally in your theme. You can also do this on a case-by-case basis using the FormLabel asterisk class via the InputLabel props.
Below are the relevant portions from your code that I changed. Also note that the default behavior for the asterisk is for it to be red if the input is in an "error" state. For instance if you add the error property to the TextField the asterisk will be red, but that also has additional effects on styling beyond the asterisk.
const styles = {
labelAsterisk: {
color: "red"
}
};
<InputLabel
FormLabelClasses={{
asterisk: this.props.classes.labelAsterisk
}}
required
shrink
htmlFor="age-native-simple"
>
Age
</InputLabel>
<TextField
required
InputLabelProps={{
shrink: true,
FormLabelClasses: {
asterisk: this.props.classes.labelAsterisk
}
}}
id="standard-name"
label="Name"
margin="normal"
helperText="Some important text"
/>
const StyledApp = withStyles(styles)(App);
//import createTheme and ThemeProvider at the top
import { createTheme, ThemeProvider } from '#mui/material/styles';
const abc = () => {
//add the theme at the top of your arrow function
const theme = createTheme({
components: {
MuiFormLabel: {
styleOverrides: {
asterisk: { color: "red" },
},
},
},
})
return ( // wrap your jsx with <ThemeProvider>
<ThemeProvider theme={theme}>
<TextField required
id="outlined-required"
label="Full Name"
type="text"
size='small'
/>
</ThemeProvider>
)
}
For those who are looking answer for MUI v5 with TextField outlined variant
const theme = createTheme({
components:{
MuiInputLabel:{
styleOverrides:{
asterisk:{
color:"#d32f2f"
}
}
}
}
});
Try this simple and easy
render(){
const name = <p>Name<span style={{ color: "red" } >*</span></p>
const email = <p>Email<span style={{ color: "red" } >*</span></p>
.
.
.
return (
<div>
<TextField type="text" label={name} />//or Input tag
<TextField type="email" label={email} />//or Input tag
.
.
.
</div>
)
}

How to override FormHelperText styles in React Material-UI?

I'm using React Material-UI library and don't understand how to override FormHelperText styles?
const { classes } = this.props
...
<TextField
name='username'
label='Username'
error={this.state.usernameInvalid}
helperText={this.state.usernameError}
classes={{
root: classes.textField,
FormHelperText: classes.helperText // <-- how to override by right way?
}}
onChange={this.handleInputChange}
/>
...
export default withStyles(styles)(SignInPopup)
styles:
const styles = () => ({
textField: {
width: '100%'
},
helperText: {
position: 'absolute',
bottom: '-50%'
}
})
I've got this error:
Warning: Material-UI: the key `FormHelperText` provided to the classes property is not implemented in FormControl.
You can only override one of the following: root,marginNormal,marginDense,fullWidth
The solution is here:
<TextField
name='username'
label='Username'
className={classes.textField}
error={this.state.usernameInvalid}
helperText={this.state.usernameError}
FormHelperTextProps={{ classes: { root: classes.helperText } }} // <- smth like that
onChange={this.handleInputChange}
/>
This turned out to be the solution for styling this prop:
const styles = {
helper: {
color: 'blue',
fontSize: '.8em',
}
}
return(
<TextField
...
FormHelperTextProps={{ style: styles.helper }}
/>
);
The solution for me was to add styling:
FormHelperTextProps={{ style: { color: theme.palette.metalgrey.main } }}

Material UI: Remove up/down arrow dials from TextView

I have this TextView in Material UI:
<TextField
id="contact phone number"
label="Contact phone number"
type="number"
value={this.state.contactPhoneNumber}
onChange={this.handleChange('contactPhoneNumber')}
placeholder="Contact phone number"
margin="normal"
/>
It looks like this:
How would I remove the up and down arrow dials from the TextView?
You can try css approach for that.
input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
From the TextField docs, the type prop accepts valid HTML input types. I believe the reason the up and down arrows are present is because you specified number as the type.
Try type="tel" instead, as it seems to be the standard input type for phone numbers.
Here is a reference to the tel type and why it's a good idea to use it. Note that if the current browser doesn't support it, it will fall back to being a regular text field.
In React v 17.0.2 and Material-UI v 4.11.4, this works for me:
import { makeStyles } from '#material-ui/core/styles';
import TextField from '#material-ui/core/TextField';
const useStyles = makeStyles({
input: {
'& input[type=number]': {
'-moz-appearance': 'textfield'
},
'& input[type=number]::-webkit-outer-spin-button': {
'-webkit-appearance': 'none',
margin: 0
},
'& input[type=number]::-webkit-inner-spin-button': {
'-webkit-appearance': 'none',
margin: 0
}
},
});
export default function MyComponent() {
const classes = useStyles();
return <TextField className={classes.input} />;
}
This works for me (css help: https://www.w3schools.com/howto/howto_css_hide_arrow_number.asp)
input: {
background: theme.palette.secondary.main,
border: `1px solid white`,
flex: 1,
padding: '8px',
'&[type=number]': {
'-moz-appearance': 'textfield',
},
'&::-webkit-outer-spin-button': {
'-webkit-appearance': 'none',
margin: 0,
},
'&::-webkit-inner-spin-button': {
'-webkit-appearance': 'none',
margin: 0,
},
},
For Material UI version 5
const Input = styled(MuiInput)(({ theme }) => ({
"& input::-webkit-outer-spin-button, & input::-webkit-inner-spin-button": {
display: "none",
},
"& input[type=number]": {
MozAppearance: "textfield",
},
}));
And then use it as
<Input
id="contact phone number"
label="Contact phone number"
type="number"
value={this.state.contactPhoneNumber}
onChange={this.handleChange('contactPhoneNumber')}
placeholder="Contact phone number"
margin="normal"
/>
The question is old but maybe this answer may help those who are still seeking a valid answer.
If you use an outlined textfield you can create a class like,
textfieldClass: {
'& .MuiOutlinedInput-input': {
'&::-webkit-outer-spin-button, &::-webkit-inner-spin-button': {
'-webkit-appearance': 'none',
},
}
},
If you use underlined textfield;
textfieldClass: {
'& .MuiInput-input': {
'&::-webkit-outer-spin-button, &::-webkit-inner-spin-button': {
'-webkit-appearance': 'none',
},
}
},
then you can use it in TextField like:
<TextField
className={classes.textfieldClass}
id="contact phone number"
label="Contact phone number"
type="number"
value={this.state.contactPhoneNumber}
onChange={this.handleChange('contactPhoneNumber')}
placeholder="Contact phone number"
margin="normal"
/>
Material-Ui v5 beta
MuiInput: {
styleOverrides: {
root: {
'& input::-webkit-outer-spin-button, & input::-webkit-inner-spin-button':
{
display: 'none',
},
'& input[type=number]': {
MozAppearance: 'textfield',
},
},
},
},
Just change the type="number" to type="tel"
In my case, if I set it as type=tel then, I will be able to type letters also inside the field which I do not want it. Instead, I did the below one and it worked for me
const StyledInput= styled(OutlinedInput)`
input[type='number']::-webkit-inner-spin-button,
input[type='number']::-webkit-outer-spin-button {
display: none;
}`;
<StyledInput
type="number"
inputProps={{ min: 0 }}
onChange={event => {
...
}}
/>
Change TextField attribute type from number to tel
For Example:
<TextField label="Phone No" type="number" required />
To
<TextField label="Phone No" type="tel" required />

Change TextField font color in MUI?

I'm currently using MUI.
And I'm having issues trying to change the font color of the multiline TextField.
<TextField className = "textfield"
fullWidth
multiline
label = "Debugger"
rows = "10"
margin = "normal"/>
And the CSS:
.textfield {
background-color: #000;
color: green;
}
However, somehow I only get the black background and the font is still black. Does anyone know how to properly change the font color of a TextField using MUI?
In MUI v5, you can just do this using sx prop:
<TextField sx={{ input: { color: 'red' } }} />
A bit longer approach if you want something more reusable:
const options = {
shouldForwardProp: (prop) => prop !== 'fontColor',
};
const StyledTextField = styled(
TextField,
options,
)(({ fontColor }) => ({
input: {
color: fontColor,
},
}));
<StyledTextField label="Outlined" fontColor="green" />
<StyledTextField label="Outlined" fontColor="purple" />
Live Demo
I referred this page TextField API
And I override the TextField using Classes
const styles = theme => ({
multilineColor:{
color:'red'
}
});
Apply the class to TextField using InputProps.
<TextField
className = "textfield"
fullWidth
multiline
InputProps={{
className: classes.multilineColor
}}
label = "Debugger"
rows = "10"
margin = "normal" />
EDIT In older version you have to specify the key input
<TextField
className = "textfield"
fullWidth
multiline
InputProps={{
classes: {
input: classes.multilineColor
}
}}
label = "Debugger"
rows = "10"
margin = "normal"
/>
Hope this will work.
Using inputProps is correct, as others have posted. Here's a slightly simpler example:
<TextField
multiline
inputProps={{ style: { color: "red" } }}
/* ... */
/>
How to set color property and background property of Text Field
import PropTypes from "prop-types";
import { withStyles } from "#material-ui/core/styles";
import TextField from "#material-ui/core/TextField";
const styles = {
root: {
background: "black"
},
input: {
color: "white"
}
};
function CustomizedInputs(props) {
const { classes } = props;
return (
<TextField
defaultValue="color"
className={classes.root}
InputProps={{
className: classes.input
}}
/>
);
}
CustomizedInputs.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles)(CustomizedInputs);
//textfield customization
const CssTextField = withStyles({
root: {
'& .MuiInputBase-root': {
color: 'white',
},
},
})(TextField);
This should work !
import { TextField, makeStyles } from "#material-ui/core";
const useStyles = makeStyles((theme) => ({
input: {
color: "#FFF",
},
}));
const MyInput = () => {
const classes = useStyles();
return (
<TextField
inputProps={{ className: classes.input }}
id="outlined-basic"
label="Write something..."
variant="outlined"
/>
);
};
export default MyInput;
If you are looking for a more generic fix, you can change your theme to contain that color, in my case I needed to change the input background and the disabled as well, so I end up using the ThemeProvider and a custom Theme.
Custom theme
const theme = createTheme({
components: {
MuiInputBase: {
styleOverrides: {
root: {
backgroundColor: '#fff',
'&.Mui-disabled': {
backgroundColor: '#e4e4e4',
},
},
},
},
},
});
const withDefaultTheme =
<P extends object>(Component: React.ComponentType<P>) =>
(props: any) =>
(
<ThemeProvider theme={theme}>
<Component {...props} />
</ThemeProvider>
);
This is working in my case:
import React from 'react';
import { TextField, } from '#mui/material';
import { makeStyles } from "#mui/styles";
const useStyles = makeStyles((theme) => ({
textfield_input: {
color: `#c5cae9 !important`,
}
}));
function Videoedit() {
const classes = useStyles();
return (<div>
<TextField
value={title}
required
label="Title"
variant="filled"
inputProps={{className: classes.textfield_input}}
color="primary"
focused
/>)
</div>;
}
export default Videoedit;
if you are using styled component with TextField then just write this code inside your styled component:
input: {
color: '#ffffff',
},
if you want to change placeholder color:
label: {
color: '#ffffff',
},
Use your Component like below
const MyTextField = withStyles({
root: {
"& .MuiInputBase-root.Mui-disabled": {
color: "rgba(0, 0, 0,0.0)"
},
"& .MuiFormLabel-root.Mui-disabled": {
color: "rgba(0, 0, 0,0.0)"
},
}
})(TextField);
Try below css
.textfield{
color: #000;
}

Resources