MaterialUI / ReactJS: MobileDatePicker not closing after date select - reactjs

Using closeOnSelect on this, but after selecting a date it remains open - only escaping or clicking OK or Cancel buttons does it disappear. I am using this on both desktop and mobile.
<LocalizationProvider dateAdapter={AdapterDateFns}>
<MobileDatePicker
style={{ width: '100%' }}
label={"Date From"}
inputFormat="dd/MM/yyyy"
closeOnSelect={true}
views={['day']}
value={abc}
renderInput={(params) => <TextFields {...params} fullWidth />}
/>
</LocalizationProvider>
How do I make sure this closes after selecting date?

Set disableCloseOnSelect prop to false.
<LocalizationProvider dateAdapter={AdapterDateFns}>
<MobileDatePicker
style={{ width: '100%' }}
label={"Date From"}
inputFormat="dd/MM/yyyy"
disableCloseOnSelect={false}
views={['day']}
value={abc}
renderInput={(params) => <TextFields {...params} fullWidth />}
/>
</LocalizationProvider>
Check codesandbox https://codesandbox.io/s/date-picker-material-ui-forked-so0v14

I made a slight change in your code. I hope it can help you:
you have to add required props for your date picker, e.g. {onChange, value }
datePickers won't accept style as props here
import * as React from "react";
import TextField from "#mui/material/TextField";
import { AdapterDateFns } from "#mui/x-date-pickers/AdapterDateFns";
import { LocalizationProvider } from "#mui/x-date-pickers/LocalizationProvider";
import { MobileDatePicker } from "#mui/x-date-pickers/MobileDatePicker";
export default function MaterialUIPickers() {
const [value, setValue] = React.useState<Date | null>(
new Date("2014-08-18T21:11:54")
);
const handleChange = (newValue: Date | null) => {
setValue(newValue);
};
return (
<LocalizationProvider dateAdapter={AdapterDateFns}>
<MobileDatePicker
label={"Date From"}
inputFormat="dd/MM/yyyy"
value={value}
views={["day"]}
onChange={handleChange}
renderInput={(params) => <TextField {...params} fullWidth />}
/>
</LocalizationProvider>
);
}

Related

Disable manual input for MUI TimePicker

I have a bit of a custom TimePicker provided from Material UI. I add an ability for the user to select only whole hours, such as 15:00, 16:00 etc. by clicking on a clock icon
What I want to achieve is to add same for manual input of the text field. For now user can manually add any valid time, for example 14:34, which is incorrect for my case
Can anyone help me?
Here is my TimePicker:
<LocalizationProvider dateAdapter={AdapterDateFns} locale={locale}>
<TimePicker
ampm={false}
openTo="hours"
views={['hours']}
inputFormat="HH:mm"
mask="__:__"
value={dayStartValue}
InputAdornmentProps={{
position: 'start',
}}
components={{
OpenPickerIcon: ClockFilledIcon,
}}
onChange={(newValue) => {
setDayStartValue(newValue)
}}
renderInput={(params) =>
<TextField
{...params}
helperText="Input start of Day time"
/>
}
/>
</LocalizationProvider>
You can control and validate the user's input when he clicks away from the time picker by using onBlur inside InputProps.
import * as React from "react";
import TextField from "#mui/material/TextField";
import { AdapterDateFns } from "#mui/x-date-pickers/AdapterDateFns";
import { LocalizationProvider } from "#mui/x-date-pickers/LocalizationProvider";
import { TimePicker } from "#mui/x-date-pickers/TimePicker";
export default function BasicTimePicker() {
const [dayStartValue, setDayStartValue] = React.useState<Date | null>(null);
return (
<LocalizationProvider
dateAdapter={AdapterDateFns}
locale={locale}
>
<TimePicker
ampm={false}
openTo="hours"
views={["hours"]}
inputFormat="HH:mm"
mask="__:__"
value={dayStartValue}
InputAdornmentProps={{
position: "start"
}}
components={{
OpenPickerIcon: ClockFilledIcon,
}}
onChange={(newValue: Date, keyboardInputValue?: string) => {
setDayStartValue(newValue);
}}
renderInput={(params) => (
<TextField {...params} helperText="Input start of Day time" />
)}
InputProps={{
onBlur: (
e: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement, Element>
) => {
const newDate = new Date(dayStartValue);
newDate.setMinutes(0);
if (e.target.value && e.target.value.length === 5) {
setDayStartValue(newDate);
}
}
}}
/>
</LocalizationProvider>
);
}
For the validation we check the user input and if it's a valid Date (5 characters length), we create a new Date with that and set the minutes to 0.
Code Sandbox example
You can change your input format and the mask to only accept whole hours like so:
<LocalizationProvider dateAdapter={AdapterDayjs}>
<TimePicker
ampm={false}
openTo="hours"
views={['hours']}
inputFormat="HH:00"
mask="__:00"
value={value}
InputAdornmentProps={{
position: 'start',
}}
onChange={(newValue) => {
setValue(newValue)
}}
renderInput={(params) =>
<TextField
{...params}
helperText="Input start of Day time"
/>
}
/>
</LocalizationProvider>
sandbox

Use mui styled for mui-x datepicker

I wanted to customize the datepicker and tried to remove the padding from the input in the mui-x datepicker but nothing was working.
Am i doing something wrong here or is styled not supported by mui-x?
import { styled } from '#mui/material/styles';
import { DesktopDatePicker, LocalizationProvider } from '#mui/x-date-pickers';
import { DatePicker } from '#mui/x-date-pickers/DatePicker';
import { AdapterDateFns } from '#mui/x-date-pickers/AdapterDateFns';
import { TextField } from '#mui/material';
const DateDisplay = styled(DesktopDatePicker)(({ theme }) => ({
'& input':{
padding: 0,
},
}));
return (
<ModalDialog>
<div>
<LocalizationProvider dateAdapter={AdapterDateFns}>
<DateDisplay
value={new Date()}
readOnly
onChange={() => {}}
renderInput={(params) => <TextField {...params} />}
></DateDisplay>
</LocalizationProvider>
</div>
</ModalDialog>
);
};
Use sx={{}} prop.
<DateDisplay
value={new Date()}
readOnly
onChange={() => {}}
renderInput={(params) => (
<TextField
{...params}
sx={{
'.MuiInputBase-input': {padding: 0},
}}
/>
)}
></DateDisplay>
With '.MuiInputBase-input' class, you can customize your <TextField> render input for your DatePicker.(You can also see it in the picture)

React and MUI: How to fix the MobileDateRangePicker start date to current date and not allow to change it?

How to fix the MobileDateRangePicker start date to current date and not allow to change it in the following code?
import { MobileDateRangePicker, LocalizationProvider } from '#mui/lab';
.....
<LocalizationProvider .....>
<MobileDateRangePicker
startText="Start"
endText="End"
.....
renderInput={(startProps, endProps) => (
<React.Fragment>
<TextField {...startProps} />
<Box sx={{ mx: 2 }}> - </Box>
<TextField {...endProps} />
</React.Fragment>
)}
/>
</LocalizationProvider>
Note: To simplify the code I used ..... notation, because in the React ... has already a meaning in the code syntax.
Start by giving the start date an initial value:
const [value, setValue] = React.useState([new Date(), null]);
Set only endDate on change:
function handleChange([newStartDate, newEndDate]) {
console.log(newEndDate);
setValue(([startDate]) => [startDate, newEndDate]);
}
...
<MobileDateRangePicker
disablePast
startText="Start"
endText="End"
value={value}
onChange={handleChange}
...
Add disabled to inputProps of the start's TextField:
<TextField
{...startProps}
inputProps={{
...startProps.inputProps,
disabled: true,
}}
/>
Optional: Add the disablePast property to the <MobileDateRangePicker /> component

MUI Autocomplete's 'defaultValue' not working when used with Controller of react-hook-form

I am trying to use MUI's Autocomplete with react-hook-form. I have wrapped an Autocomplete component in React Hook Form's Controller. When I try to set defaultValue to AutoComplete it does not work, when I try to change the preset value the Autocomplete component breaks.
Here is the snippet from my code.
<Controller
name="combo-box-demo"
control={control}
defaultValue={top100Films.find(film => film.year === selectedFilmYear)}
as={
<Autocomplete
id="combo-box-demo"
options={top100Films}
getOptionLabel={option => option.title}
style={{ width: 300 }}
renderInput={params => (
<TextField {...params} label="Combo box" variant="outlined" />
)}
/>
}
/>
Sandbox link of working demo code is here.
You should add an onChange prop on the Controller and return the selected object value
Also you can then implement getOptionSelected AutoComplete
export default function ComboBox() {
const { control } = useForm({});
const [selectedFilmYear, setSelectedFilmYear] = React.useState(1994);
return (
<Controller
name="combo-box-demo"
control={control}
defaultValue={top100Films.find(film => film.year === selectedFilmYear)}
onChange={([val, obj]) => obj}
as={
<Autocomplete
id="combo-box-demo"
options={top100Films}
getOptionSelected={(obj, newval) => obj.name === newval.name}
getOptionLabel={option => option.title}
style={{ width: 300 }}
renderInput={params => (
<TextField {...params} label="Combo box" variant="outlined" />
)}
/>
}
/>
);
}

How to clear the autocomplete's input in Material-ui after an onChange?

In the hooks version of material UI I can't seem to be able to clear the autocomplete after an onChange event:
// #flow
import React, { useRef, useState } from "react";
import "./Autocomplete.scss";
import AutocompleteUI from "#material-ui/lab/Autocomplete";
import TextField from "#material-ui/core/TextField";
function Autocomplete(props) {
const { options } = props;
const [value, setValue] = useState();
const container = useRef();
const input = useRef();
function onChange(event, newValue) {
if (!newValue) return;
props.onChange(newValue);
setValue(undefined);
input.current.value = "";
event.target.value = "";
}
function renderInput(params) {
return (
<TextField
inputRef={input}
{...params}
inputProps={{
...params.inputProps,
autoComplete: "disabled", // disable autocomplete and autofill
}}
margin="none"
fullWidth
/>
);
}
return (
<div className="Autocomplete-container">
{value}
<AutocompleteUI
ref={container}
options={options}
autoHightlight={true}
clearOnEscape={true}
autoSelect={true}
// freeSolo={true}
getOptionLabel={option => option.title}
renderInput={renderInput}
value={value}
onChange={onChange}
/>
</div>
);
}
export default Autocomplete;
Diving into the source code I've noticed the component uses useAutocomplete hook internally. However, neither setInputValue nor resetInputValue which live internally inside that hook are exposed outside. Is there a way to accomplish an input clear after an onChange?
You need to set the inputValue prop to your valueState and on onhange function just clear the valueState
<Autocomplete
inputValue={valueState}
onChange={(value, option) =>
{
setOptions([])
setValueState("")
}}
renderInput={params => (
<TextField
dir="rtl"
onChange={(event) =>
{
setValueState(event.target.value)
}}
{...params}
label="Search Patient"
variant="filled"
InputProps={{
...params.InputProps,
endAdornment: (
<React.Fragment>
{loading ? (
<CircularProgress color="inherit" size={20} />
) : null}
{params.InputProps.endAdornment}
</React.Fragment>
)
}}
/>
)}
/>
I had the same issue and I solved it with this :
const [search, setSearch] = useState("");
...
<Autocomplete
id="grouped-demo"
options={tagsList}
getOptionLabel={(option) => option.tag}
onChange={(event, value) =>value ? setSearch(value.tag) : setSearch(event.target.value)}
style={{width: 700}}
renderInput={(params) => <TextField {...params} label="Search" variant="outlined"/>}
/>
I encountered a similar scenario using Autocomplete/Textfield in a Search/Nav bar. The value would always be left behind after using a history.push or other Router function in the onChange event. The trick is to set the inputValue = "" . Every time the component renders, the previous value will be removed. See below
<Autocomplete
{...defaultProps}
onChange={(event, value) => {
if(value)
router.history.push(`/summary`);
}}
filterOptions={filterOptions}
clearOnEscape={true}
inputValue=""
renderInput={params => <TextField {...params}
label="Quick Search" fullWidth
InputProps={{...params.InputProps,
'aria-label': 'description',
disableUnderline: true,
}}/>}
/>
yo! I'm pretty sure the Textfield component from material takes an "autoComplete" prop, and you can pass that the string "false". Also, it does not go in inputProps, try that out.
<Textfield autoComplete="false" />
I had the same issue and I solved it with this :
const [value, setValue] = useState(null);
Then you don't need to use refs.

Resources