Reputation: 61
Hiho,
I want to use mui in my current react project. Is there a different/better way to create forms than the following example?:
const [companyName, setCompanyName] = useState<string>("");
const [companyNameError, setCompanyNameError] = useState<boolean>(false);
const changeName = (event: React.ChangeEvent<HTMLInputElement>) => {
if(event.target.value === "") {
setCompanyNameError(true);
} else {
setCompanyNameError(false);
}
event.preventDefault();
setCompanyName(event.target.value);
}
const anyInputFieldEmpty = () => {
var result = false;
if(companyName === "") {
setCompanyNameError(true);
result = true;
} else {
setCompanyNameError(false);
}
// add the same check for all other fields. My real code has multiple input fields
return result;
}
const resetFields = () => {
setCompanyName("");
}
return (
<div>
<TextField
required
fullWidth
label="Company Name"
margin="dense"
name="companyName"
value={companyName}
onChange={changeName}
helperText={companyNameError ? "Company name is not allowed to be empty!" : ""}
error={companyNameError}
/>
<Button
sx={{ alignSelf: 'center', }}
variant="contained"
onClick={() => {
if(!anyInputFieldEmpty()) {
onSubmitClick(); // some function from somewhere else, which triggers logic
resetFields(); // This form is in a popover. The values should be resetted before the user open it again.
}
}}
>
Create
</Button>
</div>);
It feels wrong to do the validation this way if I use multiple textfields (up to 9). Its a lot of boilerplate code and if I add further validation rules (for example a minimum character count) it goes crazy.
Is this the right way to achive my goal?
T
Upvotes: 4
Views: 12270
Reputation: 2430
You can use json to generate forms directly. Few examples:
You can use standard material design or ant UI components with above libraries.
You can also add your own components.
If you have custom requirements that cannot be achieved using above, then you can use
Upvotes: 0
Reputation: 1613
I think you should check the Formik for hook-based validation and jsonforms, react-declarative from json-schema based view creation
Less code solutions is better on production, but for a learning reason it better to write real code based on hooks, contexts or redux reducers
import { useState } from "react";
import { One, FieldType } from "react-declarative";
const fields = [
{
type: FieldType.Text,
title: "First name",
defaultValue: "Peter",
name: "firstName"
},
{
type: FieldType.Text,
title: "Age",
isInvalid: ({ age }) => {
if (age.length === 0) {
return "Please type your age";
} else if (parseInt(age) === 0) {
return "Age must be greater than zero";
}
},
inputFormatterTemplate: "000",
inputFormatterAllowed: /^[0-9]/,
name: "age"
}
];
export const App = () => {
const [data, setData] = useState(null);
const handleChange = (data) => setData(data);
return (
<>
<One fields={fields} onChange={handleChange} />
<pre>{JSON.stringify(data, null, 2)}</pre>
</>
);
};
export default App;
An example project could be found on this codesandbox
Upvotes: 3
Reputation: 111
MUI does not have a native form validator i recommend using react-hook-form + yup it's pretty simple and has a lot of tutorials
https://react-hook-form.com/get-started
EXEMPLE
TextFieldComponent
import { OutlinedTextFieldProps } from '@mui/material';
import React from 'react';
import { Control, useController } from 'react-hook-form';
import { InputContainer, TextFieldStyled } from './text-field.styles';
export interface TextFieldProps extends OutlinedTextFieldProps {
control: Control;
helperText: string;
name: string;
defaultValue?: string;
error?: boolean;
}
export const TextField: React.FC<TextFieldProps> = ({
control,
helperText,
name,
defaultValue,
error,
...rest
}) => {
const { field } = useController({
name,
control,
defaultValue: defaultValue || ''
});
return (
<InputContainer>
<TextFieldStyled
helperText={helperText}
name={field.name}
value={field.value}
onChange={field.onChange}
fullWidth
error={error}
{...rest}
/>
</InputContainer>
);
};
Styles
import { TextField } from '@mui/material';
import { styled } from '@mui/material/styles';
export const TextFieldStyled = styled(TextField)`
.MuiOutlinedInput-root {
background: ${({ theme }) => theme.palette.background.paper};
}
.MuiInputLabel-root {
color: ${({ theme }) => theme.palette.text.primary};
}
`;
export const InputContainer = styled('div')`
display: grid;
grid-template-columns: 1fr;
align-items: center;
justify-content: center;
width: 100%;
`;
export const InputIconStyled = styled('i')`
text-align: center;
`;
Usage
// Validator
const validator = yup.object().shape({
email: yup
.string()
.required(translate('contact.email.modal.email.required'))
.email(translate('contact.email.modal.email.invalid')),
});
// HookForm
const {
control,
handleSubmit,
formState: { errors }
} = useForm({
resolver: yupResolver(validator)
});
// Compoenent
<TextField
label="label"
fullWidth
placeholder="placeholder
size="small"
control={control}
helperText={errors?.name?.message}
error={!!errors?.name}
name={'name'}
variant={'outlined'}
/>
Upvotes: 1
Reputation: 1510
As others have mentioned. Formik and Yup works great for validation. Formik also provides a way to easily disable your submit buttons. Here is a codesandbox : https://codesandbox.io/s/long-butterfly-seogsw?file=/src/App.js
Upvotes: 2