I have a TextField for phone numbers in a short form. And then i want to mask this form field like (0)xxx xxx xx xx.
I'm trying to use react-input-mask plugin with Material-UI. But if i want to change input value, this is not updating the my main TextField.
<TextField
ref="phone"
name="phone"
type="text"
value={this.state.phone}
onChange={this.onChange}
>
<InputMask value={this.state.phone} onChange={this.onChange} mask="(0)999 999 99 99" maskChar=" " />
</TextField>
Actually, I couldn't find any documentation for masking with Material-UI. I'm trying to figure out how can i use with another plugins.
Update
versions: material-ui 0.20.2, react-input-mask 2.0.4
Seems like the API changed a bit:
<InputMask
mask="(0)999 999 99 99"
value={this.state.phone}
disabled={false}
maskChar=" "
>
{() => <TextField />}
</InputMask>
Demo
Original
This should do the trick:
<TextField
ref="phone"
name="phone"
type="text"
value={this.state.phone}
onChange={this.onChange}
>
<InputMask mask="(0)999 999 99 99" maskChar=" " />
</TextField>
Demo:
For current version of Material-UI and react-input-mask, the following answer worked:
<InputMask
mask="(1)999 999 9999"
value={self.state.inputValue}
onChange={this.getTextFieldValue}
className={this.props.classes.textField}
>
{() => <TextField
id={attribute}
label={attribute}
name={attribute}
className={this.props.classes.textField}
margin="normal"
type="text"
/>}
</InputMask>
This is valid for current version of react-input-mask and material-ui:
<InputMask
mask="(0)999 999 99 99"
value={this.state.phone}
onChange={this.onChange}
>
{() => <TextField />}
</InputMask>
Question:
codesandbox.io/s/q8v1259oq6 please check this my label test floatingLabelText is hidden How I solve. – Thilina Sampath
Work Around:
You can controll Label Position with "floatingLabelFixed" prop. At your handleChange look to state input value.
...when create with value:
constructor(props) {
super(props);
let value = props && props.value ? props.value : '';
let floatingLabelFixed = !!value;
this.state = {
value,
floatingLabelFixed,
};
this.handleChange = this.handleChange.bind(this);
}
...when edit (onChange):
handleChange(event) {
let value = event && event.target && event.target.value ? event.target.value : '';
let floatingLabelFixed = !!value;
this.setState({
value,
floatingLabelFixed
});
}
...your input:
<TextField
onChange={this.handleChange}
value={this.state.value}
floatingLabelFixed={this.state.floatingLabelFixed}/>
You can also use https://github.com/text-mask/text-mask. Seems like a solid project, even though it is not maintained anymore.
It provides a demo page for testing stuff and some addons that I successfully used to create a custom price input field (with material ui TextField component).
There's also an example codesandbox that I found somethere in the docs page, I believe.
Copy/pasting the codesandbox example here (you would need to adjust the mask to your needs):
// ... React imports.
import MaskedInput from "react-text-mask";
import createAutoCorrectedDatePipe from "text-mask-addons/dist/createAutoCorrectedDatePipe";
const autoCorrectedDatePipe = createAutoCorrectedDatePipe("mm/dd/yyyy", {
minYear: 1900,
maxYear: 2099
});
function TextMaskCustom(props) {
const { inputRef, ...other } = props;
return (
<MaskedInput
{...other}
ref={ref => {
inputRef(ref ? ref.inputElement : null);
}}
mask={[/\d/, /\d/, "/", /\d/, /\d/, "/", /\d/, /\d/, /\d/, /\d/]}
placeholderChar={"\u2000"}
pipe={autoCorrectedDatePipe}
guide
keepCharPositions
/>
);
}
// ...
<div>
<TextField
label="react-text-mask"
value={values.textmask}
onChange={handleChange("textmask")}
InputProps={{
inputComponent: TextMaskCustom
}}
helperText="mm/dd/yyyy"
variant="outlined"
margin="dense"
/>
</div>
<InputMask
mask="99999" // Format you need implemented
value={cellNumber}
onChange={this.inputHandler}
placeholder="Cell Number"
name="cellNumber"
required disableUnderline
style={style.inputfeild}
maskChar= {'_'}> // To display when there is no character typed
{(inputProps) =>
<Input {...inputProps}/>}
</InputMask>
Just provide all your props to InputMask and then pass them as input props to the call back method in which you display your Textfield or Input field and it should work just fine.
Related
So, the main problem is, that antd form does not detect my custom input based on antd standard input:
There is a piece of form code (AddProduct):
<Form.Item
className="m-t-10"
name="price"
rules={[
{
required: true,
message: `${t('FORM.ERR.SHOP.PRICE')}`,
},
]}
>
<CurrencyInput size="small" placeholder={t('FORM.SHOP.PRICE_VAT')} name="price" />
</Form.Item>
There is my custom input (CurrencyInput):
return (
<Input size={props.size} placeholder={props.placeholder} name={props.name} type="number" prefix={settings[6].value} />
)
The problem is when I try to submit the form it does not detect currency input, throws err that this field is required. Any ideas are it possible to implement custom input, basically, it's more HOC than custom input
You need to pass to your custom component all props, because Form.Item pass to there onChange and value props
function CustomInput({size, placehodler, name, ...restProps}) {
return (
<Input size={size} placeholder={placeholder} name={name}
type="number" prefix={settings[6].value} {...restProps} />
)
}
I have a simple login dialog in my react app, whose code is as-
i am calling this function within a Modal component.
import Jenkins_logo from "images/Jenkins_logo.svg";
import Typography from "#material-ui/core/Typography";
import TextField from '#material-ui/core/TextField';
export default function JenkinsLogin(props) {
console.log("in login " )
console.log(props)
var jenkinsUsername = sessionStorage.getItem("jenkins-Username");
var jenkinsPassword = sessionStorage.getItem("jenkins-Password");
const handleChangeUsername = (props) => {
sessionStorage.setItem("jenkins-Username", props.target.value);
};
const handleChangePassword = (props) => {
sessionStorage.setItem("jenkins-Password", props.target.value);
};
return (
<div className="jenkins_paper" >
<img src={Jenkins_logo} className="jenkins_img" />
<Typography component="h1" variant="h5">
Sign in
</Typography>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
id="Username"
label="Username "
name="Username"
autoComplete="Username"
defaultValue={jenkinsUsername}
autoFocus
onChange={handleChangeUsername}
/>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
name="password"
label="Password"
type="password"
defaultValue={jenkinsPassword}
id="password"
autoComplete="current-password"
onChange={handleChangePassword}
/>
</div>
)
}
but it does not let me edit, its sort of greyed out and wont let me click on it. below image shows.
can anyone help with what am i doing wrong.
cannot edit image
Ciao, there are some problems in your code. Let me explain better what I mean.
When you use reactjs, write lines code directly in component body is always discouraged. Much better use the function provided by reactjs.
For example, if you want to manage var in reactjs component, better use component state by defining it in component constructor like this:
constructor(props) {
super(props);
this.state = {
jenkinsUsername: "",
jenkinsPassword: ""
};
console.log("in login ");
console.log(props);
}
Now, lets say you want to load from sessionStorage jenkinsUsername and jenkinsPassword previously edited. You could use a function that reactjs fires one time on component load: componentDidMount in this way:
componentDidMount() {
this.setState({
jenkinsUsername: sessionStorage.getItem("jenkins-Username"),
jenkinsPassword: sessionStorage.getItem("jenkins-Password")
});
}
Note: this.setState is another function provided by reactjs to set the state we previously defined.
Now lets define 2 handlers to set jenkinsUsername and jenkinsPassword state and to save new values in sessionStorage.
handleChangeUsername = (props) => {
sessionStorage.setItem("jenkins-Username", props.target.value);
this.setState({
jenkinsUsername: props.target.value
});
};
handleChangePassword = (props) => {
sessionStorage.setItem("jenkins-Password", props.target.value);
this.setState({
jenkinsPassword: props.target.value
});
};
And finally the render function to show/edit jenkinsUsername and jenkinsPassword:
render() {
return (
<div className="jenkins_paper">
<Typography component="h1" variant="h5">
Sign in
</Typography>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
id="Username"
label="Username "
name="Username"
autoComplete="Username"
defaultValue={this.state.jenkinsUsername}
value={this.state.jenkinsUsername} //current value for TextBox
autoFocus
onChange={this.handleChangeUsername} //handle to manage TextField value (note the **this**)
/>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
name="password"
label="Password"
type="password"
defaultValue={this.state.jenkinsPassword}
value={this.state.jenkinsPassword}
id="password"
autoComplete="current-password"
onChange={this.handleChangePassword}
/>
</div>
);
}
This is the correct way to work with reactjs.
Here a codesanfbox example. Edit your values and try to reload the page: you will see previous data coming from sessionStorage.
I'm unable to figure out how to render outlined input type(one of the standard Material-UI input styles when used with text mask).
I copied the code sample from here: https://material-ui.com/components/text-fields/
But it only gives a sample for regular(underlined) input but nothing for outlined.
This is what i'm trying to do but it doesnt work:
const ExpirationMask = props => {
const { inputRef, ...other } = props
return <MaskedInput
{...other}
ref={ref => {inputRef(ref ? ref.inputElement : null)}}
mask={[/\d/, /\d/,'/' ,/\d/, /\d/]}
placeholderChar={'\u2000'}
/>
}
<FormControl
variant='outlined' //this doesnt work
fullWidth
>
<InputLabel>Expiration</InputLabel>
<Input
value={ccExpiration}
onChange={(e, v) => setCCExpiration(e.target.value)}
placeholder='MM/YY'
variant='outlined' //this doesnt work either
inputComponent={ExpirationMask}
/>
</FormControl>
I found a solution for it. I didn't realize that TextField is just a wrapper for the Input.
There is also another wrapper for the Input which is called OutlinedInput. So this was exactly what I ended up using:
<FormControl
fullWidth
margin='dense'
>
<InputLabel
classes={{ root: classes.expInputRoot }}
error={ccExpiration.trim().length < 5}
color='primary'>
Expiration
</InputLabel>
<OutlinedInput
value={ccExpiration}
onChange={(e, v) => setCCExpiration(e.target.value)}
label="Expiration"
placeholder='MM/YY'
error={ccExpiration.trim().length < 5}
inputComponent={ExpirationMask}
/>
</FormControl>
In doing so i encountered another problem however with an InputLabel that wasn't aligning properly(not sure if it is a bug or what), so i ended up manually changing styles for it like this:
expInputRoot: {
margin:'-8px 0 0 14px'
}
I have tried a couple of ways in order to make the material UI's autocomplete field of type required but I am not getting the behavior that I wanted. I had encapsulated my field inside react hook form <Controller/> yet no luck. I want to trigger message 'Field is mandatory' on submit when nothing is added to the field.
Below is the code snippet, I have not removed comments so that it becomes a bit easier for others to understand the approach that I had followed earlier -
<Controller
name="displayName"
as={
<Autocomplete
value={lists}
multiple
fullWidth
size="small"
limitTags={1}
id="multiple-limit-lists"
options={moduleList}
getOptionLabel={(option) => option.displayName}
renderInput={(params,props) => {
return (
<div>
<div className="container">
<TextValidator {...params} variant="outlined" label="Display Name*" className="Display Text"
name="displayName" id="outlined-multiline-static"
placeholder="Enter Display-Name" size="small"
onChange={handleDisplay}
// validators={['required']} this and below line does throw a validation but the problem is this validation stays on the screen when user selects something in the autocomplete field which is wrong.
// errorMessages={['This field is required']}
// withRequiredValidator
/>
</div>
</div>
)
}}
/>
}
// onChange={handleDisplay}
control={control}
rules={{ required: true }}
// required
// defaultValue={options[0]}
/>
<ErrorMessage errors={errors} name="displayName" message="This is required" />
You can use the following logic to get it worked. Though this might not be the best solution but works.
<Autocomplete
renderInput={(params) => (
<TextField
{...params}
label={value.length === 0 ? title : title + " *"} //handle required mark(*) on label
required={value.length === 0}
/>
)}
/>
I tried using the built in required in textfield for autocomplete, and it works like a charm. Maybe you can use this as a reference.
<Autocomplete
renderInput={(params) => {
<TextField {...params} required />
}
// Other codes
/>
Since you are rendering <TextValidator>, you should apply mandatory(required) attribute to that component not on <AutomComplete>.
Try this if your Material UI version is v5
<TextField
{...params}
required
label="Tags"
value={value}
InputProps={{
...params.InputProps,
required: value.length === 0,
}}
/>
I use material UI and a field text of type TextField. But when I was seized in my field email, the seizure does not appear to the screen and the value does not change in the email field.It always remains the same value.
Handle change is not working. the value is not passing to the handleChanges remains the same value
<TextField fullWidth={true}
className={classes.margin}
label={<FormattedMessage id="LoginTemplate.email" defaultMessage="Email" />}
id="email"
ref="email"
name="eamil"
type="email"
value={authentification.email}
onChange={this.handleChange}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<Email className={classes.inputIconsColor} />
</InputAdornment>
),
}}
/>
Here is the code. Correct me What is the issue in that
Thanks in Advance.
In order to make the value change, you need to change a state (in the screen or external).
For instance (with bad performance but just to explain):
add to your cunstrunctor if exists:
constructor(props) {
super(props);
this.state = {
emailInputText: undefined //or empty string
}
}
Then change TextField component value and onChange props to:
value={this.state.emailInputText}
onChange={(text) => this.setState({emailInputText: text})}
I will consider to remove the ref='email'.