Strange Behavior with React State and MUI TextFields - reactjs

I have a basic set of code .. That I am trying to toggle:
{(isLinkPhone) ?
<Box>
<TextField
value={phone}
label="Phone Number"
disabled
/>
</Box>
:
<Box>
<TextField
defaultValue=''
label="Link for your button *"
/>
</Box>
}
Basically what I am trying to do is during a toggle of:
const [isLinkPhone, setLinkisPhone] = React.useState(false);
I want to display one or the other .. The issue is that I can't set BOTH value AND defaultValue -- I am having a hard time understanding why React is treating this as the same input that cannot have a controlled and uncontrolled value. What I am trying to do is set the field to "nothing -> enabled/editable" if !isLinkPhone -- Else set it to "{phone} -> disabled" -- The issue is that the values "translate" between toggles.
Is there a better way to go about this? I am hesitant to create individual components for fear I will spend the time and get the same result. Can anyone explain why this is happening?

Try this
<Box>
{isLinkPhone && (
<TextField value={phone} label="Phone Number" disabled />
)}
{!isLinkPhone && (
<TextField defaultValue="" label="Link for your button *" />
)}
</Box>

Related

Field names overlapping react material UI

I have a simple react component created using material UI
function TableField(id) {
return (
<div className='flex' id={id}>
<TextField class="mr-2" id='0' label="Field type" variant="outlined" value='2' />
<TextField class="mr-2" id='1' label="Field Name" variant="outlined" value='3' />
</div>
);
}
ISSUE:
In the website the fields label are overlapping each other.
What I have tried:
As mentioned in Another StackOverflow question I tried adding values to my text fields as well but it did not work out.
What am I doing wrong here?

How to remove of MUI 5 TextField label without having notched style?

I'm working on replacing the DatePicker component in our app with the new #mui DatePicker, and I'm having some trouble getting the TextField to render without the floating label and the notched input style. Here is my latest attempt:
<LocalizationProvider dateAdapter={AdapterDateFns}>
<DatePicker
onError={(reason, value) => console.log(reason, value)}
disableOpenPicker
className={styles.datepicker}
disableMaskedInput
onChange={() => undefined}
onAccept={handleAccept}
open={datePickerVisible}
value={getSafeDate(value) as Date}
onClose={partial(handleDatepickerVisibilityChange, false)}
{...datepickerProps}
renderInput={(params) => (
<TextField
id={id}
{...inputProps}
{...params}
onChange={handleInputChange}
error={errorText !== null}
helperText={errorText}
onBlur={handleValueChange}
onKeyPress={handleKeyPress}
hiddenLabel
size='small'
fullWidth
/>
)}
/>
</LocalizationProvider>
I've tried many different combinations for TextField props, such as adding InputLabelProps={{shrink:false}}, InputLabelProps={{shrink:true}}, and inputProps={{notched:false}} but always end up looking like this:
Does anyone have an idea of how to correct this, or if it's possible?
Thanks!
The issue was fixed in release v5.4.0
​[TextField] Remove notch when no label is added (#30560) #alisasanib
Updating to v5.4.0 should solve the issue.

How to make autocomplete field of material UI required?

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,
}}
/>

Adding icon to text field based on server side validation(Formik+Yup+Material UI)

I am trying to show a tick or cross icon in a text field based on the api response.
My text field looks like this. I've added inputProps to it and added an adornment. But I want to display different icons based on a function which will return if its valid or not.
<TextField
error={errors.username && touched.username}
variant="outlined"
required
fullWidth
name="username"
label="Username"
onChange={handleChange}
helperText={touched.username && errors.username}
InputProps={{
endAdornment: (
<InputAdornment position="end" disablePointerEvents="true">
<CheckCircleOutlineIcon
style={{ color: green[500] }}
fontSize="small"
></CheckCircleOutlineIcon>
</InputAdornment>
),
}}
/>
But this keeps showing all the time, in the handleChange event i want to trigger a function which lets me decide on which icon i will show. I tried a lot of google search, but it dint help.
I see this can be achieved easily in mdBootstrap like the image i have shown, but i am using material ui and yup for validations and formik.
Please help!
Had the same issue:
My steps to fix it:
Made my Formik {Field} Module into the Material UI {Textfield} Module to be able to add the icons using the InputProps={}. This also required readding the {handleChange, handleBlur} props as validation didn't kick in on the fields otherwise.
I used endAdorment property to add the icons to the field and added conditions directly inside it to display the correct icon based on the Formik validation.
I haven't checked it with an API call validation, but I assume it works similarly with it.
<Field
component={TextField}
error={errors.username && touched.username && true}
variant="outlined"
required
fullWidth
name="username"
label="Username"
onChange={handleChange}
onBlur={handleBlur}
helperText={touched.username && errors.username}
InputProps={{
endAdornment: (
<InputAdornment position="end" disablePointerEvents="true">
{errors.username && touched.username && (
<CancelIcon
style={{ color: "red" }}
fontSize="default"
></CancelIcon>
)}
{!errors.username && touched.username && (
<CheckCircleIcon
style={{ color: "#05cc30" }}
fontSize="default"
></CheckCircleIcon>
)}
</InputAdornment>
),
}}
/>
I added conditions directly inside the endAdornment which checks for the errors.username as well as if it was touched and displays Cross or if touched and !errors.username it changes to green tick.

material ui textfield cannot editable

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'.

Resources