How to Error-validate in material ui TextField in reactjs? - reactjs

I'm using material ui TextField in my react application. I need to know how to use error and helper text validation for my below code which carry email and password?. Please go through the code given below and provide me a suitable solution.
function LoginPage() {
const handleSubmit1 = (event) => {
event.preventDefault();
const data = new FormData(event.currentTarget);
console.log({
email: data.get("email"),
password: data.get("password"),
remember: data.get("remember"),
});
};
return (
<Box
component="form"
onSubmit={handleSubmit1}
noValidate
autoComplete="off"
sx={{ mt: 1 }}
>
<FormControl sx={{ width: "60ch" }}>
<CssTextField
type="email"
id="email"
name="email"
label="Username or email"
variant="standard"
fullWidth
required
autoComplete="off"
/>
<CssTextField
name="password"
label="Password"
type="password"
id="password"
autoComplete="off"
variant="standard"
fullWidth
Validators
required
/>
</FormControl>
<Stack direction="row" spacing={2}>
<Button variant="contained" size="medium">
LOGIN
</Button>
</Stack>
</Box>
);
}

I am not quite sure what exact problem you want to solve, can you elaborate a little more in details please.
I suppose you want to validate the input in some way and show error messages according to the validation state or just simply send the login request to your authentication service. If my assumption is correct, you may want to make use of existing libraries, which will handle that for you - one of those is: mui-validate
It will handle client side validation before sending any request to a server.
Or do you actually want to display the result of an async server response?
After understanding your actual challenge better I am sure we can provide you with a good code example.

Try exploring this https://mui.com/material-ui/api/text-field/
here you have a list of all APIs MUI text-field supports if you are still not able to capture your scenario then try this https://mui.com/material-ui/react-text-field/ here you have demos of all possible text field scenarios with error ones as well, Try exploring the library documentation first as it will increase your knowledge and a better understanding of MUI package. I hope with this one you can manage your case by yourself.

Related

Form validation using regex is not working TextField MUI React

I am trying to add a regex pattern in inputProps for validation of Textfield and required but both not working, on click of next the empty or wrong input is also getting entered.
<TextField
id="outlined-basic"
name="s_firstName"
label="First Name"
variant="outlined"
defaultValue={user.s_firstName}
onChange={handleChange}
inputProps={{pattern: "[a-z]"}
required />
Please can you help what wrong is there validation not working?
Your code seems fine, and required is working if you submit the form. It shows which field is required with a mark on the label.
In material ui,
required bool
If true, the label is displayed as required and the input element is required.
You will notice a warning popup as you type in your input.
For validation, you could write your own function with onChange.
const handleValidation = (e) => {
const reg = new RegExp("[a-z]");
setValid(reg.test(e.target.value));
setValue(e.target.value);
};
With the error prop of <Textfield>, you could do something like this,
<TextField
id="outlined-basic"
name="s_firstName"
label="First Name"
variant="outlined"
value={value}
onChange={(e) => handleValidation(e)}
error={!valid}
required={true}
/>
Check out this demo for code of two scenarios.
If you want to show error message then use "helperText"
<TextField
error={value=== ""}
helperText={value=== "" ? 'Please enter a value!' : ' '}
>

How to get values of modal form antd

I'm trying to create a form inside modal using react class component and antd, but i couldn't find a way to get the data submited in the form. i tried to console the event of the onOk in antd modal but i same no data.
i also found an example but it was with function component and hooks Form.useForm()
here is the simple if anyone can help : Simple
any hint will be helpful thanks.
The solution is to hide the footer of the modal and add submit for the form exemple :
<Modal
title={this.props.formTitle}
visible={this.state.modalVisible}
confirmLoading={this.state.confirmLoading}
onCancel={this.handleCancel}
footer={[]}//this to hide the default inputs of the modal
>
<Form
layout="vertical"
name="form_in_modal"
initialValues={{
modifier: 'public',
}}
onFinish={this.handleOk}>
<Form.Item
name="title"
label="Title"
rules={[
{
required: true,
message: 'Please input the title of collection!',
},
]}>
<Input />
</Form.Item>
<Form.Item name="description" label="Description">
<Input type="textarea" />
</Form.Item>
<Form.Item name="modifier" className="collection-create-form_last-form-item">
<Radio.Group>
<Radio value="public">Public</Radio>
<Radio value="private">Private</Radio>
</Radio.Group>
//this is the submit of the form
<Button key="submit" type="primary" loading={this.state.confirmLoading} htmlType="submit">
submit
</Button>
</Form.Item>
</Form>
</Modal>
I tried this out myself with limited TS(JS) knowledge using Antd & React framework.
The steps are as follow.
construct an object e.g:
let obj1 = {
variableA : "",
variableB : ""
}
In your form body get the value using
<Form.Item ... onChange={(event)=>obj1.variableA=event.target.value}/>
In this case, the event keyword will return the final input value to instances (e.g variableA) within obj1 with given input from different form, which you can operate on after the form submission finish in a quasi-java style.
You can test it by creating alert(obj1.variableA) or console.log function to see if that's the desired value, in my case it works well with string and numeric input.
As I am not doing front end, so I might make mistakes and do feel free to point it out.

React-Final-Form delays in taking input with render props in Field

I am currently working on a react project. I am using react-final-form for fetching the data in the form. As I am using the material UI component to create the form I am creating the form somewhat like this.
Code
<Form
onSubmit={onSubmit}
validate={validate}
render={({ handleSubmit, values }) => (
<form onSubmit={handleSubmit}>
<FormControl variant="outlined" className={classes.formControl} key={fieldKey}>
<Field
name={field.fieldName}
render={({ input }) => (
<TextField
{...input}
className={classes.textField}
variant="outlined"
label={props.field.label}
placeholder={props.field.description}
required={props.field.isMandatory}
InputLabelProps={{
shrink: true,
}}
/>
)}
type="text"
/>
</FormControl>
</form>
)}
/>
Now as soon as I remove the input props from the render props it is working fine. but with the input props, it delays in taking input. Without input props, I could not fetch the value from the form.
Is there any way to resolve this time delay?
Thanks in advance.
If you want a simple field. Maybe you can pass on only essential props.
<TextField
name={input.name}
value={input.value}
onChange={input.onChange}
/>
The solution to this is subscriptions.
The form is initially rendered on every action, react-final-form allows to handle subscription,
<Form subscription={{handeleSubmit: true}} ...> </Form>
We can do somewhat like this
There is a video link for this. Video
Hope you find this helpful 😉

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.

Cypress can't find Material-UI's textarea

I'm building a React app. I use Material-UI version 3.9.3 for my components and Cypress with Cypress Testing Library for my E2E tests.
I have a multiline <TextField /> for which I want to write some tests. When you give the multiline prop to TextField it renders for some reason three textarea tags. One of these has a visibility of hidden, but still contains a value. There is also a visible one containing the value, but further down in the tree.
<TextField
id="outlined-name"
label="Name"
className={classes.textField}
value={this.state.name}
onChange={this.handleChange('name')}
margin="normal"
variant="outlined"
multiline={true}
/>
When I try to target it with the cypress tests, they fail because they say the element isn't visible:
it('inputs some new values but resets them', () => {
cy.visit('/');
cy.getByDisplayValue(/lena/i).type('{backspace}nard');
cy.getByDisplayValue(/inner five/i).select('Distants');
cy.queryByDisplayValue(/lena/i).should('not.exist');
cy.getByDisplayValue(/lennard/i).should('exist');
cy.getByText(/saving/i).should('exist');
cy.getByDisplayValue(/lena/i).should('exist');
cy.queryByDisplayValue(/lennard/i).should('not.exist');
cy.getByText(/saved/i).should('exist');
});
Throws:
Error: CypressError: Timed out retrying: cy.type() failed because this element is not visible:
<textarea aria-hidden="true" class="MuiPrivateTextarea-textarea-221 MuiPrivateTextarea-shadow-222" readonly="" rows="1" tabindex="-1">Lena</textarea>
This element '<textarea.MuiPrivateTextarea-textarea-221.MuiPrivateTextarea-shadow-222>' is not visible because it has CSS property: 'visibility: hidden'
Fix this problem, or use {force: true} to disable error checking.
How can I get this test to pass while still providing reliable information?
You have a couple main options. One option is to primarily leverage getByLabelText to get the element. The label is tied to the appropriate, visible element of the three so it works reliably. Then just verify the value of the textarea rather than using the value to get the element.
Example:
it('inputs some new values but resets them', () => {
cy.visit('https://50wv5x5p1x.codesandbox.io/');
cy.getByLabelText("Name").invoke("val").should("eq", "lena");
cy.getByLabelText("Name").type('{backspace}nard');
cy.getByLabelText("Name").invoke("val").should("eq", "lennard");
});
Another option would be to use version 4 of Material-UI. The first beta version was released today and the first stable release is targeted for mid-May. Textareas have been completely reworked in v4 and no longer render the two hidden textareas, so the following just works:
it('inputs some new values but resets them', () => {
cy.visit('https://6lj3ymm9qw.codesandbox.io/');
cy.getByDisplayValue(/lena/i).type('{backspace}nard');
cy.queryByDisplayValue(/lena/i).should('not.exist');
cy.getByDisplayValue(/lennard/i).should('exist');
});
Try with inputProps:
<TextField
inputProps={{
'id': "outlined-name"
}}
label="Name"
className={classes.textField}
value={this.state.name}
onChange={this.handleChange('name')}
margin="normal"
variant="outlined"
multiline={true}
/>
and then you get it with the id:
cy.get('[id="outlined-name"]')

Resources