React Hook Form is not submitting - reactjs

I'm new with react form, I'm using Material UI and Controller Component, and I'm sending a React Hook form request but not getting any response, form's (HTML form tag) onSubmit event is occurring but handleSubmit is not working I have one more form like that it is working perfectly fine but I don't know why it's not working, can anybody please help me with that
import { Button, useTheme, Grid, TextField, Typography } from '#mui/material';
import WSSelectBox from 'components/common/WSSelect';
import React, { FC } from 'react';
import { Controller, FormProvider, useForm } from 'react-hook-form';
import { isMobile } from 'utils/mediaqueries';
import CheckBoxButton from '../CheckBoxButton';
import { formTypes } from './utils';
import { yupResolver } from '#hookform/resolvers/yup';
import * as yup from 'yup';
import { FormPropTypes } from './type';
const schema = yup
.object()
.shape({
name: yup.string().required(),
residentialCountry: yup.number().required(),
initiator: yup.string().required(),
program: yup.string().required(),
list: yup.string().required(),
})
.required();
const Entities: FC<FormPropTypes> = ({
handleClick,
selectedType,
handleSearch,
}) => {
const theme = useTheme();
const methods = useForm({
resolver: yupResolver(schema),
});
const { handleSubmit, control } = methods;
const onSubmit = (data) => {
// Backend is not done yet
console.log('DataData', data);
};
return (
<FormProvider {...methods}>
<form
onSubmit={(e) => {
e.preventDefault();
console.log('skdjskd', 'Line no 44');
handleSubmit(onSubmit);
}}
>
<Grid container spacing={'16px'}>
{formTypes.map((type) => (
<Grid item xs={6} sm={'auto'} md={'auto'} key={type}>
<CheckBoxButton
key={type}
name={'type'}
value={type}
handleClick={handleClick}
active={type == selectedType ? true : false}
/>
</Grid>
))}
</Grid>
<Grid container pt={4} columnSpacing="20px" rowSpacing={'16px'}>
<Grid item xs={12} sm={12} md={6}>
<Controller
name="name"
render={({
// eslint-disable-next-line #typescript-eslint/no-unused-vars
field: { value, ...otherFieldProps },
fieldState,
}) => (
<TextField
fullWidth
id="sanctions-form-name"
label="Name"
variant="outlined"
helperText={
<p
style={{
position: 'relative',
left: -13,
fontSize: 12,
}}
>
Try to enter the full name or part of it. It is possible
to use original language or the Latin alphabet.
</p>
}
required
error={!!fieldState.error}
{...otherFieldProps}
/>
)}
/>
</Grid>
<Grid item xs={12} sm={6} md={3}>
<WSSelectBox
id="sanctions-form-residential-country"
label="Residential country"
name={'residentialCountry'}
data={['Ten', 'Twenty']}
handleSelect={() => {}}
type={'text'}
control={control}
/>
</Grid>
<Grid item xs={12} sm={6} md={3}>
<WSSelectBox
data={['Ten', 'Twenty']}
handleSelect={() => {}}
id="sanctions-form-initiator"
name={'initiator'}
label="Initiator"
type="text"
control={control}
/>
</Grid>
<Grid item xs={12} sm={6} md={6}>
<WSSelectBox
id="sanctions-form-program"
label="Program"
data={['Ten', 'Twenty']}
handleSelect={() => {}}
type="text"
name={'program'}
control={control}
/>
</Grid>
<Grid item xs={12} sm={6} md={6}>
<WSSelectBox
id="sanctions-form-list"
label="List"
data={['Ten', 'Twenty']}
handleSelect={() => {}}
type={'text'}
name={'list'}
control={control}
/>
</Grid>
</Grid>
<Grid
container
pt={{ xs: '20px', md: '30px' }}
rowSpacing="10px"
alignItems="center"
sx={{
[isMobile(theme)]: {
textAlign: 'center',
},
}}
justifyContent="left"
>
<Grid item xs={6} sm={'auto'}>
<Button
variant="contained"
color="primary"
sx={{
minWidth: '200px',
['#media (max-width:460px)']: {
minWidth: '120px',
},
}}
type="submit"
>
Search
</Button>
</Grid>
<Grid item xs={6} sm={'auto'}>
<Button
sx={{
minWidth: '200px',
color: '#3883FA',
['#media (max-width:460px)']: {
minWidth: '120px',
},
}}
type="submit"
>
Reset
</Button>
</Grid>
</Grid>
</form>
<Typography
variant="body2"
sx={{ fontSize: 17, color: '#121E3D', marginTop: '20px' }}
>
Use filters to start your search.
</Typography>
</FormProvider>
);
};
export default Entities;
SELECT BOX
import { TextField, MenuItem, styled, Select } from '#mui/material';
import { Controller, useForm } from 'react-hook-form';
export type SelectBoxProps = {
label: string;
id: string;
data: Array<string>;
handleSelect: VoidFunction;
type: string;
Control: () => {};
};
const SelectBox = styled(TextField)`
& .MuiOutlinedInput-root:focus {
&.Mui-focused fieldset {
border-bottom: none !important;
}
}
`;
const WSSelectBox = ({
label,
id,
data,
handleSelect,
name,
type,
control,
}) => {
return (
<>
<Controller
name={name}
render={({ field }) => (
<SelectBox
defaultValue=""
fullWidth
autoComplete="off"
id={id}
type={type}
label={label}
variant="outlined"
required
select
{...field}
>
{data.map((opt) => (
<MenuItem key={opt} value={opt}>
{opt}
</MenuItem>
))}
</SelectBox>
)}
control={control}
/>
</>
);
};
export default WSSelectBox;

Related

Required property from React hook form does not validate on textfields

I'm currently using React-hook-form to manage my textfields and that includes validation.
The problem right now is that the required property does not work well, because it does not show the little helpertext under the inputfield when it is empty.
Here is there a snippet of the UI, it only shows a few of the inputfields to save you the
unnecessary JSX code
This is how i have done it:
import { FragmentType, useFragment } from '#gql/fragment-masking';
import { graphql } from '#gql/gql';
import { Gender } from '#gql/graphql';
import {
Button,
Card,
CardContent,
Grid,
MenuItem,
TextField,
TextFieldProps,
Typography,
} from '#mui/material';
import { AdapterDayjs } from '#mui/x-date-pickers/AdapterDayjs';
import { DesktopDatePicker } from '#mui/x-date-pickers/DesktopDatePicker';
import { LocalizationProvider } from '#mui/x-date-pickers/LocalizationProvider';
import dayjs, { Dayjs } from 'dayjs';
import { useTranslation } from 'next-i18next';
import React, { useCallback, useState } from 'react';
import { useForm } from 'react-hook-form';
type Inputs = {
firstName: string;
lastName: string;
birthdate: string;
street: string;
postalcode: string;
city: string;
country: string;
gender: string;
email: string;
leveloftrust: string;
lastsignedin: string;
};
export const PatientInfoFragment = graphql(/* GraphQL */ `
fragment PatientInfo on Patient {
addresses {
city
lines
postalCode
}
birthDate
email
gender
id
name {
firstName
lastName
}
status {
lastSignInAt
levelOfTrust
}
}
`);
interface PatientInfoProps {
patient: FragmentType<typeof PatientInfoFragment>;
}
export function PatientInfo(props: PatientInfoProps) {
const patient = useFragment(PatientInfoFragment, props.patient);
const [value, setValue] = React.useState<Dayjs | null>(
dayjs(patient.birthDate)
);
const genderValueArray = Object.values(Gender);
const [disabled, setDisabled] = useState(true);
const { register, handleSubmit } = useForm<Inputs>({
defaultValues: {
firstName: patient.name?.firstName ?? '',
lastName: patient.name?.lastName ?? '',
birthdate: patient.birthDate ?? '',
country: '',
gender: patient.gender,
email: patient.email ?? '',
leveloftrust: patient.status?.levelOfTrust,
lastsignedin: patient.status?.lastSignInAt,
postalcode: patient.addresses[0]?.postalCode ?? '',
city: patient.addresses[0]?.city ?? '',
street: patient.addresses[0]?.lines[0] ?? '',
},
shouldUseNativeValidation: true,
});
const handleChange = React.useCallback(
(newValue: Dayjs | null) => setValue(newValue),
[]
);
const { t } = useTranslation();
const handleEditClick = useCallback(() => setDisabled(!disabled), [disabled]);
const renderInputField = React.useCallback(
(params: JSX.IntrinsicAttributes & TextFieldProps) => {
return <TextField {...params} />;
},
[]
);
const onSubmit = (data: any) => console.log(data);
return (
<Card>
<CardContent>
<form onSubmit={handleSubmit(onSubmit)}>
<Grid container direction="row" justifyContent="space-between">
<Grid item>
<Typography gutterBottom variant="h5" component="div">
{t('patient.info.title', 'Personal Information')}
</Typography>
</Grid>
<Grid item>
<Grid container justifyContent="space-between" sx={{ m: 1 }}>
{!disabled && (
<Button
onClick={handleEditClick}
size="large"
variant="outlined">
Cancel
</Button>
)}
<Button
onClick={handleEditClick}
size="large"
type="submit"
variant="contained">
{!disabled
? t('patient.setToComplete', 'Set to complete')
: t('patient.edit', 'Edit')}
</Button>
</Grid>
</Grid>
</Grid>
<Grid container direction="row">
<Grid
container
sx={{ margin: 1 }}
rowSpacing={3}
spacing={{ md: 4 }}>
<Grid item>
<TextField
{...register('firstName', { required: 'Field needs to be filled out' })}
label="Name"
name="firstName"
id="component-outlined"
disabled={disabled}
/>
</Grid>
<Grid item>
<TextField
{...register('lastName', {
required: 'Field needs to be filled out',
})}
label="lastname"
name="lastName"
id="component-outlined"
disabled={disabled}
/>
</Grid>
<Grid item sx={{ width: '274.67px' }}>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<DesktopDatePicker
{...register('birthdate', {
required: 'Field needs to be filled out',
})}
label="Birthdate"
inputFormat="MM/DD/YYYY"
value={value}
onChange={handleChange}
renderInput={renderInputField}
disabled={disabled}
/>
</LocalizationProvider>
</Grid>
</Grid>
<Grid
container
sx={{ margin: 1 }}
rowSpacing={3}
spacing={{ md: 4 }}>
<Grid item>
<TextField
{...register('street')}
id="component-outlined"
label="Street"
name="street"
disabled={disabled}
/>
</Grid>
<Grid item>
<TextField
{...register('postalcode')}
id="component-outlined"
label="Postal code"
name="postalCode"
disabled={disabled}
/>
</Grid>
<Grid item>
<TextField
{...register('city')}
id="component-outlined"
label="City"
name="city"
disabled={disabled}
/>
</Grid>
</Grid>
<Grid
container
sx={{ margin: 1 }}
rowSpacing={3}
spacing={{ md: 4 }}>
<Grid item>
<TextField
{...register('country')}
id="component-outlined"
label="Country"
name="country"
disabled={disabled}
/>
</Grid>
<Grid item>
<TextField
sx={{ width: '242.67px' }}
id="outlined-select-gender"
select
{...register('gender')}
label="Gender"
disabled={disabled}
value={patient.gender}>
{genderValueArray.map(option => (
<MenuItem key={option} value={option}>
{option}
</MenuItem>
))}
</TextField>
</Grid>
<Grid item>
<TextField
{...register('email')}
id="component-outlined"
label="Email"
name="email"
disabled
/>
</Grid>
</Grid>
<Grid
container
sx={{ margin: 1 }}
rowSpacing={3}
spacing={{ md: 4 }}>
<Grid item>
<TextField
{...register('leveloftrust')}
id="component-outlined"
label="Level of trust"
name="leveloftrust"
disabled
/>
</Grid>
<Grid item>
<TextField
{...register('lastsignedin')}
id="component-outlined"
label="Last signed in"
name="lastsignedin"
disabled
/>
</Grid>
</Grid>
</Grid>
</form>
</CardContent>
</Card>
);
}
If you're using React Hook Form with MUI Textfield, you'll need to use the Controller component wrapper from react-hook-form for your MUI Textfield components.
View Integrating with UI Libraries
For example, you would grab the Input component from MUI's Core library instead:
import Input from "#material-ui/core/Input";
Then in your form you'd wrap it using Controller like:
<Controller
name="firstName"
control={control}
render={({ field }) => <Input {...field} />}
/>
Then MUI Input has has error boolean and helperText string as available properties on the Input component. For example using Formik (but any form library would work with MUI):
<TextField
id="password"
name="password"
label="Password"
type="password"
value={formik.values.password}
onChange={formik.handleChange}
error={!!formik.errors.password && formik.touched.password}
helperText={formik.touched.password && formik.errors.password}
required
/>
Otherwise, reviewing their documentation on how to Handle Errors, it appears with no library they have you handle error output manually using the errors object from formState. You'd destructure that data like:
const { register, formState: { errors }, handleSubmit } = useForm();
Finally, they link a very handy CodeSandbox which uses a #hookform/error-message library that can wrap regular HTML inputs. If you want to stick with MUI, I'd go with the helperText and error properties.

Adding skeleton effect to form fields until props data is loaded

I'm passing JSON data pulled off a REST API via props to the component below. Since I don't pre-set a value to the "Pick a team" select field, it outputs the following warning:
MUI: You have provided an out-of-range value undefined for the select component.
Consider providing a value that matches one of the available options or ''.
which is normal, because there isn't a selected value.
How can I add skeleton effect to the form below until the props data is loaded?
<Skeleton variant="text" />
<Skeleton variant="circular" width={40} height={40} />
<Skeleton variant="rectangular" width={210} height={118} />
FormOne.tsx
import {
Box,
Button,
FormControl,
Grid,
InputLabel,
MenuItem,
Select,
SelectChangeEvent,
Typography,
} from '#mui/material';
import { useState } from 'react';
import { TeamSeason as Team } from './lib/interfaces/TeamSeason';
const FormOne = (props: any) => {
const [selectedTeam, setSelectedTeam] = useState<Team | null>(null);
const [selectedQuery, setSelectedQuery] = useState<number>(1);
const handleQueryChange = (event: SelectChangeEvent) => {
setSelectedQuery(Number(event.target.value));
};
const handleTeamChange = (event: SelectChangeEvent) => {
const team = props.data.find(
(team: Team) => team.statId === Number(event.target.value)
);
setSelectedTeam(team);
};
return (
<>
<Box mb={2}>
<Typography component="h1" variant="h4" align="center">
GUI #1
</Typography>
</Box>
<Box component="form" noValidate autoComplete="off">
<Grid container spacing={2}>
<Grid item xs={12}>
<FormControl variant="outlined" fullWidth>
<InputLabel id="team-label">Pick a team</InputLabel>
<Select
labelId="team-label"
id="team"
value={selectedTeam?.id?.toString()}
onChange={handleTeamChange}
>
{props.data.map((team: Team) => {
return (
<MenuItem key={team.statId} value={team.statId.toString()}>
{team.name} ({team.team})
</MenuItem>
);
})}
</Select>
</FormControl>
</Grid>
<Grid item xs={12}>
<FormControl variant="outlined" fullWidth>
<InputLabel id="query-label">Query</InputLabel>
<Select
labelId="query-label"
id="query"
value={selectedQuery.toString()}
onChange={handleQueryChange}
>
<MenuItem value={1}>What name does he use?</MenuItem>
<MenuItem value={2}>What abbreviature does he have?</MenuItem>
</Select>
</FormControl>
</Grid>
<Grid item xs={12}>
<Button variant="contained">Submit</Button>
</Grid>
<Grid item xs={12}>
{selectedTeam && selectedQuery === 1 && (
<p>team name: {`${selectedTeam?.name}`}</p>
)}
{selectedTeam && selectedQuery === 2 && (
<p>team abbreviature: {`${selectedTeam?.team}`}</p>
)}
</Grid>
</Grid>
</Box>
</>
);
};
export default FormOne;
index.tsx
import { useState, useEffect } from 'react';
import type { NextPage } from 'next';
import Container from '#mui/material/Container';
import Box from '#mui/material/Box';
import { DataGrid, GridColDef } from '#mui/x-data-grid';
import { Grid, Paper } from '#mui/material';
import Skeleton from '#mui/material/Skeleton';
import { blue } from '#mui/material/colors';
import FormOne from './../src/FormOne';
const LoadingSkeleton = () => (
<Box
sx={{
height: 'max-content',
}}
>
{[...Array(10)].map((_, index) => (
<Skeleton variant="rectangular" sx={{ my: 4, mx: 1 }} key={index} />
))}
</Box>
);
const columns: GridColDef[] = [
{ field: 'statId', headerName: 'Stat ID' },
{ field: 'name', headerName: 'Name', width: 200 },
{ field: 'season', headerName: 'Season' },
];
const Home: NextPage = () => {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
setInterval(
() =>
fetch('https://localhost:7000/TeamSeason/2021')
.then((response) => response.json())
.then((data) => {
setData(data);
setLoading(false);
}),
3000
);
}, []);
return (
<Container
maxWidth={false}
sx={{
height: '100vh',
overflow: 'auto',
background: `linear-gradient(to right, ${blue[200]}, ${blue[500]})`,
}}
>
<Container maxWidth="lg" sx={{ mt: 3, mb: 3 }}>
<Grid container spacing={{ xs: 2, md: 3 }}>
<Grid item xs={12} md={6}>
<Paper sx={{ padding: 3 }}>
<FormOne data={data} />
</Paper>
</Grid>
<Grid item xs={12} md={6}>
<Paper sx={{ padding: 3 }}></Paper>
</Grid>
<Grid item xs={12}>
<Paper sx={{ padding: 3 }}>
<DataGrid
getRowId={(row) => row.statId}
sx={{ height: '650px' }} // either autoHeight or this
rows={data}
columns={columns}
pageSize={10}
// autoHeight
rowsPerPageOptions={[10]}
disableSelectionOnClick
disableColumnMenu
disableColumnSelector
components={{
LoadingOverlay: LoadingSkeleton,
}}
loading={loading}
/>
</Paper>
</Grid>
</Grid>
</Container>
</Container>
);
};
export default Home;
CodeSandbox

Type '{}' is not assignable to type 'IProps'

I am using react with formik and typescript in my project. I am using withFormik HOC in my forms, code is below
import React from "react";
//Libraries import........
import {
Container,
Box,
Link,
Grid,
Checkbox,
FormControlLabel,
TextField,
CssBaseline,
Avatar,
Typography,
makeStyles,
Theme,
} from "#material-ui/core";
import LockOutlinedIcon from "#material-ui/icons/LockOutlined";
import { Form, FormikProps, FormikValues, useFormik, withFormik } from "formik";
import * as Yup from "yup";
//Components import........
import { Button } from "#components/button";
//Interfaces ..........
interface FormValues {
email?:string,
password?:string
}
interface IProps extends FormikProps<FormValues> {
// onSubmit(e:React.FormEvent<HTMLInputElement>):void
}
const useStyles = makeStyles((theme: Theme) => ({
paper: {
marginTop: theme.spacing(8),
display: "flex",
flexDirection: "column",
alignItems: "center",
},
avatar: {
margin: theme.spacing(1),
backgroundColor: theme.palette.secondary.main,
},
form: {
width: "100%", // Fix IE 11 issue.
marginTop: theme.spacing(1),
},
submit: {
margin: theme.spacing(3, 0, 2),
},
}));
const Login: React.FC<IProps> = (props) => {
const classes = useStyles();
const { handleSubmit, handleBlur, handleChange, handleReset, errors } = props;
console.log(errors);
return (
<Container component="main" maxWidth="xs">
<CssBaseline />
<div className={classes.paper}>
<Avatar className={classes.avatar}>
<LockOutlinedIcon />
</Avatar>
<Typography component="h1" variant="h5">
Sign in
</Typography>
<form className={classes.form} noValidate>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
id="email"
label="Email Address"
name="email"
autoFocus
/>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
name="password"
label="Password"
type="password"
id="password"
autoComplete="current-password"
/>
<FormControlLabel
control={<Checkbox value="remember" color="primary" />}
label="Remember me"
/>
<Button
type="submit"
fullWidth
variant="contained"
color="primary"
className={classes.submit}
>
Sign In
</Button>
<Grid container>
<Grid item xs>
<Link href="#" variant="body2">
Forgot password?
</Link>
</Grid>
<Grid item>
<Link href="#" variant="body2">
{"Don't have an account? Sign Up"}
</Link>
</Grid>
</Grid>
</form>
</div>
<Box mt={8}></Box>
</Container>
);
};
export const LoginView = withFormik<IProps, FormValues>({
enableReinitialize: true,
mapPropsToValues: (props) => {
console.log(props);
return { email: "", password: "" };
},
validationSchema: Yup.object({
// email: Yup.string().required(),
}),
handleSubmit: (values) => {
console.log(values);
},
})(Login);
and then when in my project i import and use LoginView inside my pages like
import React from "react";
import { LoginView } from "#components/user/login";
const Home: React.FC = (props: any) => {
return (
<div
style={{ display: "flex", flexDirection: "column", minHeight: "100vh" }}
>
<LoginView />
</div>
);
};
export default Home;
i get an error where i write
Type '{}' is not assignable to type 'IProps'. Type '{}' is missing
the following properties from type 'FormikState': values,
errors, touched, isSubmitting, and 2 more.
First Generic Type provided to withFormik shouldn't extend from FormikValues.
Define IProps like this
interface IProps {
// onSubmit(e:React.FormEvent<HTMLInputElement>):void
}
See this https://codesandbox.io/s/stackoverflow-69143042-wlvz9

Transfer data to dialog box when clicked

I would like when clicking on my accordion, the data in this line will go into the form of my dialog box. But I am not receiving any data in the form.
Why is the form not receiving the data?
import React, { useEffect, useState } from 'react';
import clsx from 'clsx';
import PropTypes from 'prop-types';
import moment from 'moment';
import PerfectScrollbar from 'react-perfect-scrollbar';
import {
Avatar,
Box,
Card,
Accordion,
AccordionSummary,
AccordionDetails,
Grid,
SvgIcon,
InputAdornment,
CardContent,
TextField,
ListItemText,
ListItem,
List,
Checkbox,
Table,
TableBody,
TableCell,
TableHead,
TablePagination,
IconButton,
Typography,
makeStyles,
Button
} from '#material-ui/core';
import ExpandMoreIcon from '#material-ui/icons/ExpandMore';
import getInitials from 'src/utils/getInitials';
import EditProjAdminE from './editProjAdminE';
import AjoutEven from './ajoutEven';
import dataEven from './data';
import SpeedDialTooltipOpen from './speedDialE';
import EditIcon from '#material-ui/icons/Edit';
import AddIcon from '#material-ui/icons/Add';
import { Search as SearchIcon } from 'react-feather';
import { Slide } from 'react-slideshow-image';
import axios from "axios";
import DeleteIcon from '#material-ui/icons/Delete';
const useStyles = makeStyles((theme) => ({
root: {},
absolute: {
position: 'absolute',
bottom: theme.spacing(2),
right: theme.spacing(3),
},
avatar: {
marginRight: theme.spacing(2)
}
}));
const ProjetAdminE = ({ className, dataEleve, ...rest }) => {
const classes = useStyles();
// const [data, setData] = useState(dataEven);
const [filteredEven, setFilteredEven] = useState([]);
const [dataSearch, setDataSearch] = useState([]);
const [loading, setLoading] = useState(false);
const [limit, setLimit] = useState(10);
const [page, setPage] = useState(0);
const [selectedeleveIds, setSelectedeleveIds] = useState([]);
// const dateR = new Date()
// const dateReel = dateR.setDate(dateR.getDate()+1);
const handleLimitChange = (event) => {
setLimit(event.target.value);
};
const handlePageChange = (event, newPage) => {
setPage(newPage);
};
const [search, setSearch] = useState('');
useEffect(() => {
setLoading(true);
axios
.get("http://localhost:8080/employees")
.then((res) => {
setDataSearch(res.data);
setLoading(false);
})
.catch((err) => {
console.log(err);
});
}, []);
const suppression = (id) => {
fetch('http://localhost:8080/evenement/' + id, {
method: 'DELETE',
})
.then(res => res.text())
.then(res => {
// setDataSearch(res.data);
console.log(res)
})
alert(JSON.stringify("événement Numéro " + id + " supprimé"))
}
// const modification =(id) =>{
// fetch('http://localhost:8080/update/' + id, {
// method: 'PUT',
// })
// .then(res => res.text())
// .then(res => console.log(res))
// alert(JSON.stringify("événement Numéro " +id+ " modifié"))
// }
// alert(JSON.stringify(index))
useEffect(() => {
setFilteredEven(
dataSearch.filter((Evenen) =>
Evenen.descrip_evene.toLowerCase().includes(search.toLowerCase())
)
);
}, [search, dataSearch]);
return (
<Card
className={clsx(classes.root, className)}
{...rest}
>
<>
<Box
display="flex"
justifyContent="left"
style={{ height: 30 }}
>
<Typography variant="h3" style={{ margin: 10, color: '#1565C0' }}>
LISTE DES EVENEMENTS
</Typography>
</Box>
<Box mt={3}>
<Card>
<CardContent>
<Box maxWidth={500}>
<TextField
value={search}
onChange={e => {
setSearch(e.target.value);
}}
fullWidth
InputProps={{
startAdornment: (
<InputAdornment position="start">
<SvgIcon
fontSize="small"
color="action"
>
<SearchIcon />
</SvgIcon>
</InputAdornment>
)
}}
placeholder="Recherchez un évenement"
variant="outlined"
/>
</Box>
{/* <Button
color="primary"
variant="contained"
onClick = {alert(JSON.stringify(dateReel))}
>
Rechercher
</Button> */}
</CardContent>
</Card>
</Box>
<Grid>
<Grid spacing={1} md={8} xs={12} style={{ margin: 2 }}>
{filteredEven.map((recherche, index) => (
<Accordion style={{ marginTop: 30 }} >
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel1a-content"
id="panel1a-header"
style={{ backgroundColor: '#DADFD9' }}
>
<Grid container spacing={1} md={12} xs={12} style={{ margin: 0 }}>
<Grid item md={2} xs={4}>
{recherche.date_even.slice(0, 10)}
</Grid>
<Grid item md={2} xs={2}>
{recherche.prix_even}
</Grid>
<Grid item md={2} xs={3}>
{recherche.statut}
</Grid>
<Grid item md={3} xs={3}>
{recherche.descrip_evene}
</Grid>
<Grid item md={3} xs={8} style={{ marginTop: -10 }}>
<IconButton>
<EditProjAdminE
dataSearch={dataSearch}
setDataSearch={setDataSearch}
id={recherche.id}
/>
</IconButton>
<IconButton
onClick={async () => {
suppression(recherche.id)
window.location.reload(false)
}}
>
<DeleteIcon fontSize="small" style={{ color: 'black' }} />
</IconButton>
{/* <SpeedDialTooltipOpen/> */}
</Grid>
</Grid>
</AccordionSummary>
<AccordionDetails>
<List>
<ListItem>
<ListItemText primary={
<Typography variant="caption" style={{ fontWeight: 'bold', fontSize: 16 }}>
{recherche.id}
</Typography>
}
secondary="Membre concerné"
/>
</ListItem>
<ListItem>
<ListItemText primary={
<Typography variant="caption" style={{ fontWeight: 'bold', fontSize: 16 }}>
{recherche.lieu}
</Typography>
}
secondary="Lieu"
/>
</ListItem>
<ListItem>
<ListItemText primary={
<Typography variant="caption" style={{ fontWeight: 'bold', fontSize: 16 }}>
{recherche.heure}
</Typography>
}
secondary="Heure"
/>
</ListItem>
</List>
</AccordionDetails>
</Accordion>
))}
</Grid>
</Grid>
<AjoutEven />
</>
</Card>
);
};
// Results.propTypes = {
// className: PropTypes.string,
// dataEleve: PropTypes.array.isRequired
// };
export default ProjetAdminE;
editProjetEven.js
import React, { useState } from 'react';
import clsx from 'clsx';
import PropTypes from 'prop-types';
import moment from 'moment';
import PerfectScrollbar from 'react-perfect-scrollbar';
import { makeStyles, useTheme, withStyles } from '#material-ui/core/styles';
import {
Button,
Grid,
MenuItem,
DialogContent,
DialogActions,
Dialog,
IconButton,
Avatar,
TextField,
DialogTitle,
} from '#material-ui/core';
import getInitials from 'src/utils/getInitials';
import CreateIcon from '#material-ui/icons/Create';
import EditIcon from '#material-ui/icons/Edit';
import DeleteIcon from '#material-ui/icons/Delete';
const useStyles = makeStyles((theme) => ({
root: {
width: 645,
},
item: {
height: 50
},
buttonDial: {
color: "#fff",
},
buttonAnnuler: {
color: "red"
},
buttonSave: {
background: "#558b2f",
color: "#558b2f",
}
}));
export default function EditProjAdminE(setDataSearch,dataSearch,data,setData,id,index) {
const classes = useStyles();
const [open, setOpen] = React.useState(false);
const [opens, setOpens] = React.useState(false);
const handleChange = event => {
const { name, value } = event.target
setDataSearch({ ...dataSearch, [name]: value })
}
// const fullScreen = useMediaQuery(theme.breakpoints.down(645));
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
// const handleInputChange = event => {
// const { name, value } = event.target
// setData({ ...data, [name]: value })
// }
// const item = dataSearch.find(id);
return (
<div>
<div display="flex">
<IconButton onClick={handleClickOpen}>
<EditIcon fontSize="small" alt="modifier" style={{ color: '#205723' }} />
</IconButton>
</div>
<Dialog
fullWidth
// fullScreen
open={open }
onClose={handleClose}
aria-labelledby="responsive-dialog-title"
maxWidth = 'md'
>
{/* { index ==="" ? "aucune information":
<> */}
<DialogTitle id="responsive-dialog-title">Virement</DialogTitle>
<DialogContent >
<Grid container spacing={1}>
<Grid item md={4} xs={12}>
<TextField
fullWidth
margin="dense"
type="text"
name="prix_even"
value={dataSearch.prix_even}
// defaultValue={dataSearch.prix_even}
label="Prix"
variant="outlined"
onChange={(event) => handleChange(event)}
/>
</Grid>
<Grid item md={4} xs={12}>
<TextField
fullWidth
margin="dense"
type="text"
name="heure"
value={dataSearch.heure}
label="Heure"
variant="outlined"
onChange={(event) => handleChange(event)}
/>
</Grid>
<Grid item md={4} xs={12}>
<TextField
fullWidth
margin="dense"
type="text"
name="lieu"
value={dataSearch.lieu}
label="Lieu"
variant="outlined"
onChange={(event) => handleChange(event)}
/>
</Grid>
<Grid item md={4} xs={12}>
<TextField
fullWidth
margin="dense"
type="date"
name="date_even"
value={dataSearch.date_even}
helperText="Date de l'événement"
variant="outlined"
onChange={(event) => handleChange(event)}
/>
</Grid>
<Grid item md={4} xs={12}>
<TextField
fullWidth
margin="dense"
type="text"
name="descrip_even"
value={dataSearch.descrip_even}
label="Descr de l'événement"
variant="outlined"
onChange={(event) => handleChange(event)}
/>
</Grid>
<Grid item md={4} xs={12}>
<TextField
fullWidth
margin="dense"
type="text"
name="statut"
value={dataSearch.statut}
label="Statut"
variant="outlined"
onChange={(event) => handleChange(event)}
/>
</Grid>
</Grid>
</DialogContent>
<DialogActions>
<Button
// onClick={alert(JSON.stringify(dataSearch))}
>
Modifier
</Button>
<Button onClick={handleClose} className={classes.buttonAnnuler}>
Fermer
</Button>
</DialogActions>
{/* </>
} */}
</Dialog>
</div>
);
}
on click I pass the index of the object to the array and send it to a new array that I created
<IconButton onClick={async () => {
setData({ ...dataSearch[index] })
handleClickOpen()
}}
>
<EditIcon fontSize="small" alt="modifier" style={{ color: '#205723' }} />
</IconButton>
The handleClickOpen seems to be only opening the dialog box and not invoking setDataSearch({ ...dataSearch, [name]: value }) which seems to be responsible to add values to the dataSearch object that is used in your form fields.
I would personally double check if the EditProjAdminE component is receiving the proper dataSearch and then later call a similar function to handleChange when the open event is triggered.

how to preview the selected image upload React js

Have created a button called image upload, need to view the selected image when selected
<GridItem xs={6}>
<FormControl className={classes.formControl}>
<input
accept="image/*"
className={classes.input}
style={{ display: 'none' }}
id="raised-button-file"
multiple
type="file"
/>
<label htmlFor="raised-button-file">
<Button
variant="raised"
component="span"
className={classes.button}
>
Upload Image
</Button>
</label>
</FormControl>
</GridItem>
you can set the file object URL in the state during the onChange and use it in an img tag like this,
const [file, setFile] = useState(undefined);
const handleChange = (event) => {
setFile(URL.createObjectURL(event.target.files[0]));
}
use this handleChange method in input onChange event,
<GridItem xs={6}>
<FormControl className={classes.formControl}>
<input
accept="image/*"
className={classes.input}
style={{ display: 'none' }}
id="raised-button-file"
multiple
type="file"
onChange={handleChange}
/>
{/* preview of file */}
{ file && <img src={this.state.file}/>}
<label htmlFor="raised-button-file">
<Button
variant="raised"
component="span"
className={classes.button}
>
Upload Image
</Button>
</label>
</FormControl>
</GridItem>
also if you want to allow the user to crop the image selected there is this library react-image-crop. I use it and it works pretty good for me.
before select
select image
Typescript
import { Grid, IconButton, makeStyles, Tooltip } from '#material-ui/core'
import { PhotoCamera, Publish } from "#material-ui/icons"
import React, { useState } from 'react'
import { useDispatch } from 'react-redux'
import { IRequestState } from '../../assets/interfaces'
const FILE = 'ImageUpload.tsx'
const useStyles = makeStyles((theme) => ({
root: {
'& > *': {
margin: theme.spacing(1),
},
}, right: {
float: "right"
}, w100: {
width: "100%"
}, input: {
display: "none",
},
faceImage: {
color: theme.palette.primary.light,
}, success: {
color: theme.palette.success.main
}
}))
interface IImageUploadProps {
Submit(event: React.MouseEvent<HTMLButtonElement>): void
}
type IImageUploadState = IRequestState & {
imageFile?: any
}
export default function ImageUpload(props: IImageUploadProps) {
const classes = useStyles()
const dispatch = useDispatch()
const initState: IImageUploadState = { inited: false, requesting: false }
const [values, setState] = useState<IImageUploadState>(initState)
const handleCapture = ({ target }: any) => {
if (target && target.files && target.files.length)
setState({ ...values, imageFile: target.files[0] })
}
return (
<>
<Grid
container
direction="row"
justify="space-evenly"
alignItems="center"
spacing={2}
>
<Grid item sm={6} md={3}>
<Grid
justify="center"
alignItems="center"
container
>
<Grid item>
<input
accept="image/jpeg"
className={classes.input}
id="faceImage"
type="file"
onChange={handleCapture}
/>
<Tooltip title="select image">
<label htmlFor="faceImage">
<IconButton
className={classes.faceImage}
color="primary"
aria-label="upload picture"
component="span"
>
<PhotoCamera fontSize="large" />
</IconButton>
</label>
</Tooltip>
</Grid>
</Grid>
</Grid>
<Grid item sm={6} md={3}>
<img className={classes.w100} hidden={!values.imageFile} src={values.imageFile && URL.createObjectURL(values.imageFile)} alt="Logo" />
</Grid>
<Grid item sm={6} md={3}>
<Grid
justify="center"
alignItems="center"
container
>
<Grid item>
<Tooltip title="upload image">
<IconButton
className={classes.success}
aria-label="upload"
onClick={props.Submit}
edge="end"
disabled={!values.imageFile}
>
<Publish />
</IconButton>
</Tooltip>
</Grid>
</Grid>
</Grid>
</Grid>
</>
)
}

Resources