Calendar popup needed to be closed after selecting the date - javascript

The calendar popup is not getting closed after selecting the date and it's wrapped in a label tag with an image and the calendar component. if I'm removing the label tag image tag is not activating the calendar popup.
`<label style={{width:"100%"}}>
<DatePicker
dateFormat="dd/MM/yyyy"
placeholderText="Select Date"
onChange={onChange}
minDate={props.minDate ? props.minDate : null}
maxDate={props.maxDate ? props.maxDate : null}
className={props.className}
style={{ width: '100%', marginTop:"-10px" }}
selected={props.value && props.value !== "" ? new Date(props.value) : null}
showDisabledMonthNavigation
/>
<img
src="./images/calendar.png"
className="custom-input-icon img-fluid"
alt="c"
style={{ top: '25px' }}
/>
</label>`
so I tried calling the component using onClick event but it's not really working. i don't know how to do it. any help would be much appreciated.
<>
<DatePicker
dateFormat="dd/MM/yyyy"
placeholderText="Select Date"
onChange={onChange}
minDate={props.minDate ? props.minDate : null}
maxDate={props.maxDate ? props.maxDate : null}
className={props.className}
style={{ width: '100%', marginTop:"-10px" }}
selected={props.value && props.value !== "" ? new Date(props.value) : null}
showDisabledMonthNavigation
/>
<img onClick={handleclick}
src="./images/calendar.png"
className="custom-input-icon img-fluid"
alt="c"
style={{ top: '25px' }}
/>
</>
handling click???
const handleclick = () => {console.log('ello');

you need to wrap it like this but if i press the preselected date (current date) it won't close the popup so i need to click away to close it
import { DatePicker, LocalizationProvider } from '#mui/lab'
import roLocale from 'date-fns/locale/ro';
import DateAdapter from '#mui/lab/AdapterDateFns';
import { TextField } from '#mui/material';
const [error, setError] = useState(false)
const [value, setValue] = useState<Date | null>(null)
const handleChange = (newValue: Date | null) => {
setValue(newValue)
}
{/* const handleValidation = () => {
if (error) {
alert(error)
}
} */}
<LocalizationProvider dateAdapter={DateAdapter} locale={roLocale}>
<DatePicker inputFormat="dd/MM/yyyy"
label={label}
openTo="year"
value={value}
// onError={err => setError(err ? true : false)}
onChange={(newValue: Date | null) => handleChange(newValue)}
maxDate={MIN_DATE}
minDate={MAX_DATE}
renderInput={(params) => <TextField variant="standard"
// onBlur={handleValidation}
fullWidth
required={true}
color="secondary"
{...params} />} />
</LocalizationProvider>

Related

How can I prevent my datepicker getting re-focussed after clicking another input

I have a Datepicker of Material that opens if you click on the textfield it belongs to. If you try to select another textfield while the datepicker is opened it will target/focus back to the datepicker.
Note: This issue is also for targeting nothing, it will refocus the datepicker again after closing it.
Example Demo: https://stackblitz.com/edit/react-b4xpki?file=demo.tsx
Code:
`
export default function BasicDatePicker() {
const [value, setValue] = React.useState<Dayjs | null>(null);
const [open, setOpen] = React.useState(false);
return (
<LocalizationProvider dateAdapter={AdapterDayjs}>
<TextField placeholder='Click here while datepicker is opened' fullWidth={true} sx={{mb:2, mr: 2}}/>
<DatePicker
label="Basic example"
value={value}
onChange={(newValue) => {
setValue(newValue);
}}
open={open}
onOpen={() => setOpen(true)}
onClose={() => setOpen(false)}
renderInput={(props) => (
<TextField {...props} onClick={(e) => setOpen(true)} />
)}
/>
</LocalizationProvider>
);
}
So how to reproduce to problem?
Click op the datepicker (not the icon)
Click on another textfield
Watch how the target/focus is back on the datepicker
You can create focus named state so can control in onFocus at <TextField />
firstly, create focus named state:
const [focus, setFocus] = useState(false);
TextField: if open is false in onFocus, currentTarget shouldn't be focus.
<TextField
{...props}
onFocus={(e) => {
setFocus(open);
if (!open) {
e.currentTarget.blur();
return;
}
}}
focused={focus}
onClick={(e) => setOpen((prev) => !prev)}
/>
if the value changes in DatePicker, focus should be true.
<DatePicker
label="Basic example"
value={value}
onChange={(newValue) => {
setValue(newValue);
setFocus(true);
}}
...otherProps
/>
link: https://stackblitz.com/edit/react-b4xpki-rirdxn?file=demo.tsx

React - MUI Autocomplete single selection remove event

I use material UI autocomplete to create a single-select dropdown.
But the problem is that when I click the close button placed right-side of the input, the onChange event didn't call and my state didn't update.
While in the multi-select mode this event successfully occurred.
Someone helps me to use the remove event in single-select mode.
This is my single select:
<Autocomplete<Option<T>>
onChange={(e: any, newValue) => {
if (newValue) {
handleChangeValue(newValue.value);
}
}}
sx={{ ...sx }}
id={id}
options={options}
isOptionEqualToValue={(newValue, option) =>
newValue.value === option.value
}
defaultValue={
defaultValue && {
value: defaultValue,
label: options.find((option) => option.value === defaultValue)?.label,
}
}
value={
value && {
value: value,
label: options.find((option) => option.value === value)?.label,
}
}
getOptionLabel={(option) => option.label || `${option.value}`}
renderOption={(props, option, { selected }) => (
<li value={option.value} {...props}>
<Checkbox
style={{ marginRight: 8 }}
checked={selected}
id={`${option.value}`}
/>
{option.label || `${option.value}`}
</li>
)}
renderInput={(params) => (
<TextField
value={value}
{...params}
placeholder={global.translate(placeholder)}
/>
)}
/>
this one is my multi-select autocomplete:
<Autocomplete
onChange={(e: any, value) => {
onChange(value);
}}
value={value}
sx={{ ...sx }}
multiple
id={id}
options={options}
disableCloseOnSelect
defaultValue={[...defaultValues]}
getOptionLabel={(option) => option.label}
isOptionEqualToValue={(newValue, option) =>
newValue.value === option.value
}
renderOption={(props, option, { selected }) => (
<li value={option.value} {...props}>
<Checkbox
icon={<CheckBoxOutlineBlankIcon fontSize="small" />}
checkedIcon={<CheckBoxIcon fontSize="small" />}
style={{ marginRight: 8 }}
checked={selected}
id={option.value}
/>
{option.label}
</li>
)}
renderInput={(params) => (
<TextField {...params} placeholder={placeholder} />
)}
/>
In your single-select mode Autocomplete component, you send handleChangeValue if only newValue exists.
So, in your single-select mode, you need to change this code:
<Autocomplete<Option<T>>
onChange={(e: any, newValue) => {
if (newValue) {
handleChangeValue(newValue.value);
}
}}
to this code:
<Autocomplete<Option<T>>
onChange={(e: any, newValue) => {
const valueToBeSent = newValue ? newValue.value : undefined;
handleChangeValue(valueToBeSent);
}}
in order to send onChange event on every value change.

How to pas props to MUI Datepicker

I tried changing the mui datepicker to a different format, but it always fails.
this code work for me
const Step2 = ({handlechange,value: {startTime}}) =>
{
return(
<TextField
fullWidth
required
color="success"
size="small"
label="Start Time"
name='startTime'
type="datetime-local"
value={startTime || '2022-06-24T10:30' }
InputLabelProps={{
shrink: true,
}}
margin="normal"
onChange={handlechange}
/>
)
}
export default Step2
but how to implement to MUI Datetime picker to this
const Step2 = ({handlechange,value: {startTime}}) =>
{
const [value, setValue] = React.useState(new Date());
return (
<LocalizationProvider dateAdapter={AdapterDateFns}>
<DateTimePicker
renderInput={(props) => <TextField {...props} />}
label="DateTimePicker"
value={value}
onChange={(newValue) => {
setValue(newValue);
}}/>
</LocalizationProvider>)
}
export default Step2

MUI DatePicker's shouldDisableDate prop leading to error

<Controller
name="toDate"
control={control}
defaultValue={null}
render={({ field }) => (
<DatePicker
format="DD/MM/yyyy"
value={field.value}
onChange={(e) => { setToDate(e); field.onChange(e); }}
minDate={fromDate}
shouldDisableDate={fromDate}
/>
)}
{...register("toDate",{ required: true })}
/>
I used the shouldDisableProp to disable the date which is selected inside another datepicker whose value is stored in a state variable 'fromDate'.
But when I press the datepicker it is leading to this error.
The minDate is working perfectly fine using the fromDate state variable.
The shouldDisableDate method receives a date param and expect a boolean.
import * as React from "react";
import TextField from "#mui/material/TextField";
import AdapterDateFns from "#mui/lab/AdapterDateFns";
import LocalizationProvider from "#mui/lab/LocalizationProvider";
import DatePicker from "#mui/lab/DatePicker";
export default function BasicDatePicker() {
const [value, setValue] = React.useState<Date | null>(null);
const [fromDate, setFromDate] = React.useState<Date | null>(null);
return (
<>
<LocalizationProvider dateAdapter={AdapterDateFns}>
<DatePicker
label="From Date"
value={fromDate}
onChange={(newValue) => {
setFromDate(newValue);
}}
renderInput={(params) => <TextField {...params} />}
/>
</LocalizationProvider>
<br />
<LocalizationProvider dateAdapter={AdapterDateFns}>
<DatePicker
label="To Date"
value={value}
onChange={(newValue) => {
setValue(newValue);
}}
minDate={fromDate}
shouldDisableDate={(dateParam) => {
//your_condition here
//return true to disabled and false to enable
const fromFormatted = fromDate.toISOString().split("T")[0];
const currentDate = dateParam.toISOString().split("T")[0];
return fromFormatted === currentDate ? true : false;
}}
renderInput={(params) => <TextField {...params} />}
/>
</LocalizationProvider>
</>
);
}
UpdatedCode
So do something like that and you will achieve your goal.
In your case, compare dateParam with your fromDate var, to return true or false and disable or not the date.
Edit: Now is adapted to your real case. Just check it out.

React SyntheticEvent warning being thrown even with e.persistent()

I have a couple blocks of code that sets the state of by the user enter a value into and input and even checking a checkbox. They are both throwing the classic SyntheticEvent warning:
Warning: This synthetic event is reused for performance reasons. If you're seeing this, you're accessing the property buttons on a released/nullified synthetic event.
I have tried chacheing and e.persist() and its still throwing the warning on the onChange events:
const handleChange = (e) => {
e.persist();
const { name, checked } = e.target;
setHolidayData((prevState) => ({ ...prevState, [name]: checked }));
};
const updateValues = (e) => {
e.persist();
const { name, value } = e.target;
setHolidayData((prevState) => ({ ...prevState, [name]: value }));
};
These change events are on the inputs and check boxes respectively. What am i doing wrong here that the warnings are still being thrown?
Entire Component Code:
import React, { useState, useEffect, useCallback } from 'react';
import { makeStyles, withStyles } from "#material-ui/core/styles";
import _ from "lodash";
import Slide from "#material-ui/core/Slide";
import Button from '#material-ui/core/Button';
import Dialog from '#material-ui/core/Dialog';
import MuiDialogTitle from '#material-ui/core/DialogTitle';
import MuiDialogContent from '#material-ui/core/DialogContent';
import MuiDialogActions from '#material-ui/core/DialogActions';
import IconButton from '#material-ui/core/IconButton';
import CloseIcon from '#material-ui/icons/Close';
import Typography from '#material-ui/core/Typography';
import TextField from '#material-ui/core/TextField';
import FormControlLabel from '#material-ui/core/FormControlLabel';
import Checkbox from '#material-ui/core/Checkbox';
import DateFnsUtils from '#date-io/date-fns';
import {
MuiPickersUtilsProvider,
KeyboardDatePicker,
} from '#material-ui/pickers';
import moment from 'moment';
import { toast } from 'react-toastify';
import * as actions from "../../../Redux/Actions";
import { useDispatch, useSelector } from 'react-redux';
const Transition = React.forwardRef(function Transition(props, ref) {
return <Slide direction="down" ref={ref} {...props} />;
});
const styles = (theme) => ({
root: {
margin: 0,
padding: theme.spacing(2),
},
closeButton: {
position: 'absolute',
right: theme.spacing(1),
top: theme.spacing(1),
color: theme.palette.grey[500],
},
});
const DialogTitle = withStyles(styles)((props) => {
const { children, classes, onClose, ...other } = props;
return (
<MuiDialogTitle disableTypography className={classes.root} {...other}>
<Typography variant="h6">{children}</Typography>
{onClose ? (
<IconButton aria-label="close" className={classes.closeButton} onClick={onClose}>
<CloseIcon />
</IconButton>
) : null}
</MuiDialogTitle>
);
});
const DialogContent = withStyles((theme) => ({
root: {
padding: theme.spacing(2),
},
}))(MuiDialogContent);
const DialogActions = withStyles((theme) => ({
root: {
margin: 0,
padding: theme.spacing(1),
},
}))(MuiDialogActions);
const HolidayDialog = (props) => {
const [noticeModal, setNoticeModal] = useState(props.open);
const [selectedDate, setSelectedDate] = useState(new Date());
const [holidayData, setHolidayData] = useState({});
const dispatch = useDispatch();
useEffect(() => {
setSelectedDate(moment(props.data.HolidayDate));
setNoticeModal(props.open);
setHolidayData(props.data);
}, [props.open]);
const user = useSelector(state => {
return JSON.stringify(state.main.user);
});
const handleDateChange = (date) => {
setSelectedDate(date);
};
const handleClose = () => {
props.onClose(false);
setNoticeModal(false);
};
const handleChange = (e) => {
e.persist();
const { name, checked } = e.target;
setHolidayData((prevState) => ({ ...prevState, [name]: checked }));
};
const updateValues = (e) => {
e.persist();
const { name, value } = e.target;
setHolidayData((prevState) => ({ ...prevState, [name]: value }));
};
const formSubmit = () => {
dispatch(actions.holiday_editHoliday(holidayData));
handleClose();
}
const handleSubmit = () => {
dispatch(actions.holiday_submitHoliday(holidayData));
handleClose();
}
const handleCreate = () => {
let createdHoliday = {
Active: true,
Branch: holidayData.Branch ? holidayData.Branch : '',
Close: holidayData.Close ? holidayData.Close : '',
CoOp: holidayData.CoOp ? holidayData.CoOp : false,
HolidayDate: selectedDate ? moment(selectedDate).format('MM/DD/YYYY') : moment().format('MM/DD/YYYY'),
HolidayName: holidayData.HolidayName ? holidayData.HolidayName : "",
Open: holidayData.Branch ? holidayData.Branch : '',
Phone: holidayData.Phone ? holidayData.Phone : true,
Web: holidayData.Web ? holidayData.Web : true,
Hours: holidayData.Hours ? holidayData.Hours : '',
}
dispatch(actions.holiday_createHoliday(createdHoliday));
handleClose();
}
const handlePublish = () => {
const userObj = JSON.parse(user);
const userName = `CCU\\${userObj.UserName}`;
if (userName != holidayData.SubmittedBy) {
dispatch(actions.holiday_publishHoliday(holidayData));
handleClose();
} else {
toast.error("Submitter & Publisher cannot be the same person", {
position: "top-right",
autoClose: 5000,
hideProgressBar: false,
closeOnClick: true,
pauseOnHover: false,
draggable: true,
progress: undefined,
});
handleClose();
}
}
const handleDecline = () => {
dispatch(actions.holiday_declineHoliday(holidayData));
handleClose();
}
return (
<Dialog
open={noticeModal}
TransitionComponent={Transition}
keepMounted
onClose={handleClose}
aria-labelledby="notice-modal-slide-title"
aria-describedby="notice-modal-slide-description"
>
<DialogTitle id="customized-dialog-title" onClose={handleClose}>
{holidayData.HolidayName ? holidayData.HolidayName : 'Create New Holiday'}
</DialogTitle>
<form noValidate autoComplete="off" id="HolidayForm" onSubmit={(e) => { e.preventDefault(); formSubmit(); } }>
<DialogContent dividers>
<div className="row">
<div className="col">
<TextField required name="HolidayName" id="outlined-basic" label="Holiday Name" variant="outlined" onChange={updateValues} value={holidayData.HolidayName || ''} disabled={holidayData.Submitted != null}/>
</div>
<div className="col">
<TextField id="outlined-basic" name="Branch" label="Branch" variant="outlined" onChange={updateValues} value={holidayData.Branch || ''} disabled={holidayData.Submitted != null}/>
</div>
</div>
<div className="row mt-3">
<div className="col">
<MuiPickersUtilsProvider utils={DateFnsUtils}>
<KeyboardDatePicker
disableToolbar
variant="inline"
format="MM/dd/yyyy"
margin="normal"
id="date-picker-inline"
label="Holiday Date *"
value={selectedDate}
onChange={handleDateChange}
KeyboardButtonProps={{
'aria-label': 'change date',
}}
disabled={holidayData.Submitted != null}
/>
</MuiPickersUtilsProvider>
</div>
<div className="col">
<TextField id="outlined-basic" name="Hours" label="Hours" variant="outlined" onChange={updateValues} value={holidayData.Hours || ''} disabled={holidayData.Submitted != null}/>
</div>
</div>
{holidayData.Hours ? (
<div className="row mt-3">
<div className="col">
<TextField id="outlined-basic" name="Open" label="Open" variant="outlined" onChange={updateValues} value={holidayData.Open || ''} disabled={holidayData.Submitted != null}/>
</div>
<div className="col">
<TextField id="outlined-basic" name="Close" label="Close" variant="outlined" onChange={updateValues} value={holidayData.Close || ''} disabled={holidayData.Submitted != null}/>
</div>
</div>
) : (
<div></div>
)}
<div className="row mt-3">
<div className="col d-flex flex-column">
<FormControlLabel
control={
<Checkbox
checked={holidayData.Web || false}
value={holidayData.Web}
onChange={handleChange}
name="Web"
color="primary"
disabled={holidayData.Submitted != null}
/>
}
label="Show on Web?"
/>
<FormControlLabel
control={
<Checkbox
checked={holidayData.CoOp || false}
value={holidayData.CoOp}
onChange={handleChange}
name="CoOp"
color="primary"
disabled={holidayData.Submitted != null}
/>
}
label="CoOp Holiday?"
/>
</div>
<div className="col d-flex flex-column">
<FormControlLabel
control={
<Checkbox
checked={holidayData.Phone || false}
value={holidayData.Phone}
onChange={handleChange}
name="Phone"
color="primary"
disabled={holidayData.Submitted != null}
/>
}
label="Use in IVR?"
/>
<FormControlLabel
control={
<Checkbox
checked={holidayData.Active || true}
value={holidayData.Active}
onChange={handleChange}
disabled
name="Active"
color="primary"
/>
}
label="Active"
/>
</div>
</div>
</DialogContent>
<DialogActions className="d-flex">
{holidayData.Submitted ? (
<div className="mr-auto">
<Button variant="outlined" color="primary" onClick={handlePublish}>
Publish
</Button>
<Button variant="outlined" color="secondary" className="ml-2" onClick={handleDecline}>
Decline
</Button>
</div>
) : (
<div className="mr-auto">
<Button variant="outlined" color="primary" onClick={handleSubmit}>
Submit
</Button>
</div>
)}
<Button variant="outlined" onClick={handleClose} color="default">
Cancel
</Button>
{holidayData.Active ? (
<Button variant="outlined" color="primary" type="submit" form="HolidayForm" disabled={holidayData.Submitted != null}>
Update Holiday
</Button>
) : (
<Button variant="outlined" color="primary" onClick={handleCreate} form="HolidayForm">
Create Holiday
</Button>
)}
</DialogActions>
</form>
</Dialog>
)
}
export default HolidayDialog;

Categories