How to set input direction in react-hook-form? - javascript

I'm building a website that uses "RTL (Right To Left) language", so I implemented react-hook-form, but react hook form uses only "LTR" forms like so...
In here I'm using the HTML attribute (dir="RTL") in my page, so all the text is "RTL" except the react hook form how can I fix this?.
import { TextField, Grid } from "#material-ui/core";
import { useFormContext, Controller } from "react-hook-form";
const FormInput = ({ name, label }) => {
const { control } = useFormContext();
return (
<Grid item xs={12} sm={6}>
<Controller
as={TextField} control={control} fullWidth name={name} label={label} required defaultValue=""/>
</Grid>
)
}
export default FormInput;
this is my FormInput component, I export this component to my address form component
import { useForm, FormProvider } from "react-hook-form";
<FormProvider>
<form>
<FormInput name="firstName" label="الإسم الأول (first name)" />
<FormInput name="lastName" label="اسم العائلة (last name)" />
</form>
</FormProvider>
this is my address form component.

Related

ReactJS TypeScript MUI TextField set value using useSate and add onchange event function for text filed

I am new to ReactJS with MUI development, have below ReactJS TypeScript with MuiText filed form. Looking some help to use useSate method to change the textfiled value.
Also add the onchnage function for the text filed. I can add the onchange function for normal text filed, unsure how to add it for MUI Text filed?
import * as React from 'react';
import { useState } from "react"
import Button from '#mui/material/Button';
import CssBaseline from '#mui/material/CssBaseline';
import TextField from '#mui/material/TextField';
import Grid from '#mui/material/Grid';
import Box from '#mui/material/Box';
import Container from '#mui/material/Container';
import { createTheme, ThemeProvider } from '#mui/material/styles';
import { useForm, SubmitHandler, Controller } from 'react-hook-form';
import * as yup from 'yup';
import { yupResolver } from '#hookform/resolvers/yup';
interface IFormInputs {
filepath: string;
}
const schema = yup.object().shape({
filepath: yup.string().min(4).required(),
});
const theme = createTheme();
export default function MuiTextField() {
const {
control,
handleSubmit,
formState: { errors },
} = useForm<IFormInputs>({
resolver: yupResolver(schema),
});
const [filepath, setFilepath] = useState("vodeo.mp3");
const onSubmit: SubmitHandler<IFormInputs> = (data) => {
console.log('data submitted: ', data);
console.log('filepath: ', data.filepath);
};
return (
<ThemeProvider theme={theme}>
<Container component="main" maxWidth="lg">
<CssBaseline />
<Box
sx={{
marginTop: 8,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
}}
>
<form onSubmit={handleSubmit(onSubmit)}>
<Box sx={{ mt: 3 }}>
<Grid container spacing={2}>
<Grid item xs={16} sm={6}>
<Controller
name="filepath"
control={control}
defaultValue=""
render={({ field }) => (
<TextField
{...field}
label="File Path"
error={!!errors.filepath}
helperText={errors.filepath ? errors.filepath?.message : ''}
autoComplete="file-path"
fullWidth
/>
)}
/>
</Grid>
<Button
type="submit"
variant="contained"
sx={{ mt: 3, mb: 2 }}
>
Submit
</Button>
</Grid>
</Box>
</form>
</Box>
</Container>
</ThemeProvider>
);
}
Update:
Here is the codeshare: https://codesandbox.io/s/boring-water-m47uxn?file=/src/App.tsx
When we change the text box value to auto, want to change the textbox value to audio.mp3. but its not working.
MUI Textfield have onChange too:
<TextField
error={Boolean(touched.name && errors.name)}
fullWidth
label={t('Name')}
name="name"
onBlur={handleBlur}
onChange={handleChange}
value={values.name}
variant="outlined"
autoComplete="off"
/>
'field' in render function contains onChange.
And state of form saved in useForm. In useForm props you have to add defaultValues. And you did not pass prop type="file", maybe its your problem.
Guide about create file input with react hook form: https://refine.dev/blog/how-to-multipart-file-upload-with-react-hook-form/
Textfield api: https://mui.com/material-ui/api/text-field/

Changing to '#mui/material' makes the components not rendered

I have a JS file (react) that looks like this:
import { Grid, TextField, makeStyles } from '#material-ui/core'
import React from 'react'
import {useState} from 'react'
//remove this function and refresh. see magic.
const useStyle = makeStyles(theme => ({
root:{
'& .MuiFormControl-root':{
width : '80%',
margin : theme.spacing(.75)
}
}
}))
const initialFormValues = {
id:0,
name:'',
username:'',
email:''
}
export default function EntryForm() {
const [values, setvalues] = useState(initialFormValues)
return (
<form className={useStyle().root}>
<Grid container>
<Grid item>
<TextField
size='small'
variant='outlined'
label='name'
value={values.name} />
<TextField
size='small'
variant='outlined'
label='username'
value={values.username} />
<TextField
size='small'
variant='outlined'
label='email'
value={values.email} />
</Grid>
<Grid item>
</Grid>
</Grid>
</form>
)
}
This works fine, and invoked, the fields get rendered along with it's parent components.
However, changing first line to:
import { Grid, TextField, makeStyles } from '#mui/material'
and refreshing the browser makes the whole page empty. Apparently, this happens specifically with makeStyles from '#mui/material' usage. Using Grid and Textfield from '#mui/material' only doesn't cause that.
What is happening here?
As per docs you should import makeStyles from #mui/styles.
Please try updating the import statement as:
import { makeStyles } from "#mui/styles";

React: Uploading Files (Front-End)

I am trying to make a file upload form (front-end), but I don't think my uploaded file is communicating with the initial values when submitting since only the dataset name and the contact email are changed when I try to submit the form.
Here is what the form looks like when I load the page:
I initially press submit to see what happens within the React console tools. The output looks like this Subscribe form values: {datasetName: "dataset.csv", contactEmail: "johndoe#example.com", uploadFile: "sample.csv"} which is expected.
I then change the name of the dataset, change the contact email, and choose a file.
Unfortunately, the output looks like this Subscribe form values: {datasetName: "newData.csv", contactEmail: "janedoe#example.com", uploadFile: "sample.csv"}. Notice how the uploadFile part is the same despite trying to change the values.
I am fairly new to React, and I am using Material UI to render some of the textfields and buttons. What am I missing here?
import React from 'react';
import { Form } from 'react-final-form';
import { TextField } from 'mui-rff';
import { makeStyles } from '#material-ui/core/styles';
import Button from '#material-ui/core/Button';
import Grid from '#material-ui/core/Grid';
import Input from '#material-ui/core/Input';
import { FormControl } from '#material-ui/core';
import axios from 'axios';
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
padding: theme.spacing(2)
},
}));
const onSubmit = async values => {
console.log('Subscribe form values:', values);
};
const validate = values => {
const errors = {};
if (!values.datasetName) {
errors.datasetName = 'Required';
}
if (!values.contactEmail) {
errors.contactEmail = 'Required';
}
if (!values.uploadFile) {
errors.uploadFile = 'Required';
}
return errors;
};
const UploadForm = () => {
const classes = useStyles();
return (
<div className={classes.root}>
<Form
onSubmit={onSubmit}
initialValues={{ datasetName: 'dataset.csv', contactEmail: 'johndoe#example.com', uploadFile: 'sample.csv' }}
validate={validate}
render={({ handleSubmit, form, submitting, pristine, values }) => (
<form onSubmit={handleSubmit} noValidate>
<Grid
container
justify="center"
alignItems="center"
spacing={2}>
<Grid item xs={12}>
<TextField
label="Dataset Name"
name="datasetName"
margin="none"
required={true}
/>
</Grid>
<Grid item xs={12}>
<TextField
label="Contact Email"
name="contactEmail"
margin="none"
required={true}
/>
</Grid>
<Grid item xs={12}>
<FormControl>
<Input
name='uploadFile'
type='file'
required={true}
/>
</FormControl>
</Grid>
<Grid item xs={12}>
<Button
variant="contained"
color="primary"
type="submit"
disabled={submitting}
>
Submit
</Button>
</Grid>
</Grid>
</form>
)}
/>
</div>
);
}
export default UploadForm;
Imports:
import React from 'react';
import { Form } from 'react-final-form';
import { TextField } from 'mui-rff';
import { makeStyles } from '#material-ui/core/styles';
import Button from '#material-ui/core/Button';
import Grid from '#material-ui/core/Grid';
import Input from '#material-ui/core/Input';
import { FormControl } from '#material-ui/core';
import axios from 'axios';

Delete tag in uncontrolled "ChipInput" using react hook form

I'm using react-hook-form to handle form values, Its working fine for all other input types like TextFeild, Select from material but facing issues with "material-ui-chip-input" as adding tag working fine but not able to delete tag on click of cross button or hitting backspace. I'm struggling on this from a long. Anyone please help in it.
import React from "react";
import FormControl from "#material-ui/core/FormControl";
import { Controller } from "react-hook-form";
import ChipInput from "material-ui-chip-input";
const ReactHookFormChips = ({
name,
label,
control,
defaultValue,
children,
rules,
error,
chipsError,
...props
}) => {
const labelId = `${name}-label`;
return (
<FormControl {...props}>
<Controller
as={
<ChipInput
label={label}
helperText={chipsError}
error={error}
/>
}
name={name}
control={control}
defaultValue={defaultValue}
rules={rules}
/>
</FormControl>
);
};
export default ReactHookFormChips;
calling this component like
<ReactHookFormChips
id="levelLabel"
name="tags"
label="Select Tags"
control={control}
defaultValue={[]}
margin="normal"
error={!!errors?.tags}
rules={{ required: true }}
chipsError={errors?.tags && "Tag is required."}
/>
I fixed it using render prop.
import React from "react";
import FormControl from "#material-ui/core/FormControl";
import InputLabel from "#material-ui/core/InputLabel";
import { Controller } from "react-hook-form";
import ChipInput from "material-ui-chip-input";
const ReactHookFormChips = ({
name,
label,
control,
defaultValue,
children,
rules,
error,
chipsError,
...props
}) => {
const labelId = `${name}-label`;
return (
<FormControl {...props}>
<Controller
render={({ onChange, onBlur, value }) =>
<ChipInput
onChange={onChange}
label={label}
helperText={chipsError}
error={error}
/>
}
name={name}
control={control}
defaultValue={defaultValue}
rules={rules}
/>
</FormControl>
);
};
export default ReactHookFormChips;

How to make the Button and TextField pitch perfect?

I'm trying to make a form using Material UI and React. This is what I have so far:
import React from 'react'
import {Button, TextField} from '#material-ui/core'
import AddIcon from '#material-ui/icons/Add'
import PropTypes from 'prop-types'
class AddItem extends React.Component {
state = {
text: ''
}
handleChange = e => {
this.setState({text: e.target.value})
}
render() {
return (
<form onSubmit={this.props.onSubmit(this.state.text)}>
<TextField id="task" label="Task" placeholder="e.g. Feed the fish" value={this.state.text}
onChange={this.handleChange} color="secondary" variant="outlined" size="small"/>
<Button color="secondary" variant="outlined" endIcon={<AddIcon/>} size="large">
Add
</Button>
</form>
)
}
}
AddItem.propTypes = {
onSubmit: PropTypes.func.isRequired
}
export default AddItem
The result is the following screenshot:
But wait! Can you see that? The Button height and the TextField height are just so slightly misaligned! (By 2.5px I think). Is there any way to fix this?
This is better than earlier, where the TextField was a lot bigger than the Button (my fix was size="small" on the TextField).
How can I make sure that the TextField and the Button are the same height?
I know that in Bulma there's something like a level component that helps out with that, so is there any similar solution in Material UI?
You can make your custom <Button> styled as you want.
Lets create <StyledButton> by overwriting style (padding) of outlined and large variant of button.
import { withStyles } from "#material-ui/core/styles";
const styles = {
outlinedSizeLarge: {
padding: "6px 21px" // default is "7px 21px" https://github.com/mui-org/material-ui/blob/master/packages/material-ui/src/Button/Button.js#L202
}
};
const StyledButton = withStyles(styles)(Button);
Then you can use it in your component:
<form onSubmit={this.props.onSubmit(this.state.text)}>
<TextField id="task" label="Task" placeholder="e.g. Feed the fish" value={this.state.text} onChange={this.handleChange} color="secondary" variant="outlined" size="small"/>
<StyledButton color="secondary" variant="outlined" endIcon={<AddIcon/>} size="large">Add</StyledButton>
</form>
Result:
Live demo
Did you try to use variant attribute with value outlined?
<Button variant='outlined' size='small'>Add</Button>

Categories