MUI DatePicker's shouldDisableDate prop leading to error - javascript

<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.

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

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

Formik with react-day-picker

I would like to create a form with a date picker. So i choose React DayPicker v8 now i would like to implement this picker in my current formik form.
I created a date picker component:
import React from "react";
import { Form, Popover, OverlayTrigger } from "react-bootstrap";
import { DayPicker, useInput } from "react-day-picker";
import "react-day-picker/dist/style.css";
const DatePicker = (props) => {
const { inputProps, dayPickerProps } = useInput({
format: "dd.MM.yyyy",
required: true,
});
const handleChange = (value) => {
props.onChange(props.name, value);
};
const popover = (
<Popover id="popover-basic" className="mw-100">
<Popover.Body>
<DayPicker showWeekNumber weekStartsOn={1} {...dayPickerProps} />
</Popover.Body>
</Popover>
);
return (
<>
<OverlayTrigger
rootClose
trigger="click"
placement="bottom-start"
overlay={popover}
>
<Form.Control
{...inputProps}
onChange={handleChange}
value={props.value}
name={props.name}
id={props.name}
/>
</OverlayTrigger>
</>
);
};
export default DatePicker;
DatePicker.js
<Col>
<Form.Group className="mb-3">
<Form.Label htmlFor="startdate">Start Date</Form.Label>
<DatePicker
name="startdate"
value={formikProps.values.startdate}
onChange={formikProps.setFieldValue}
/>
</Form.Group>
</Col>
Home.js
My problem is in my browser DevTools the value from datepicker changed correctly <input name="startdate" id="startdate" class="form-control" value="23.06.2022"> but in my formikProps.values.startdate I only get the old initialValue.
Additionally if i add a log event to the handleChange function in the DatePicker.js Component the log will not show up. Why?
Is this the correct way? In a react-select field this code works completely fine.
My solution was
<Popover id="popover-basic" className="mw-100">
<Popover.Body>
<DayPicker
{...dayPickerProps}
showWeekNumber
weekStartsOn={1}
onDayClick={handleChange}
/>
</Popover.Body>
</Popover>
The keyword was OnDayClick not OnChange

TypeError: props.render is not a function (React hook form)

I am passing methods as a prop in this form I am making with react-hook-form.
Its giving me (TypeError: props.render is not a function) when Controller is added in from react-hook-form. I cannot find any solutions online so any help is appreciated.
import { useForm, FormProvider } from 'react-hook-form';
import FormInput from './CustomTextField';
const AddressForm = () => {
const methods = useForm();
return (
<>
<FormProvider {...methods}>
<form onSubmit=' '>
<Grid container spacing={3}>
<FormInput required name='firstName' label='First name' />
</Grid>
</form>
</FormProvider>
</>
);
};
import { useFormContext, Controller } from 'react-hook-form';
const FormInput = ({ name, label, required }) => {
const { control } = useFormContext();
return (
<>
<Controller
as={TextField}
name={name}
control={control}
label={label}
fullWidth
required={required}
/>
<>
);
};
export default FormInput;
Was stuck in somewhat similar problem,
you can try following changes in FormInput function:
import React from 'react';
import { TextField, Grid } from '#material-ui/core';
import { useFormContext, Controller } from 'react-hook-form';
const FormInput = ({ name, label, required}) => {
const { control } = useFormContext();
const isError = false;
return (
<>
<Controller
control={control}
name={name}
render = {({ field})=> (
<TextField
fullWidth
label={label}
required
/>
)}
/>
</>
);
}
export default FormInput;
hope this helps, else you can go through the docs
I had this problem (TypeError: props.render is not a function) with react-hook-form + react-select when I tried to reuse the same Controller component from an old project, and I fixed this way:
Unchanged:
import { useForm, Controller } from "react-hook-form";
import Select from "react-select";
From:
<Controller
name="languages"
control={control}
rules={{ required: true }}
as={Select}
options={props.languageOptionsToSelect}
defaultValue={props.languageDefaultValueToSelect}
isMulti
/>;
To:
<Controller
name="languages"
control={control}
rules={{ required: true }}
render={({ field }) => (
<Select
{...field}
options={props.languageOptionsToSelect}
defaultValue={props.languageDefaultValueToSelect}
isMulti
/>
)}
/>;
It seems render prop in Controller component is required now.
This problem is arising either because you update your react-hook-form or new to react-hook-form
You just need to use render prop in Controller component
<Controller
render={({ field }) => (
<input
onChange={(e) => field.onChange(transform.output(e))}
value={transform.input(field.value)}
/>
)}
/>
or if you are using a third party Form library
import { Input, Select, MenuItem } from "#material-ui/core";
<Controller
render={({ field }) => (
<Select {...field}>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
</Select>
)}
control={control}
name="select"
defaultValue={10}
/>
Try this one!
<Controller
render={({ field }) => <TextField {...field} />}
name={name}
control={control}
label={label}
fullWidth
required={required}
/>
Add render as a prop in the Controller Component. Refer to the docs here
import React from 'react'
import { TextField, Grid } from '#material-ui/core'
import { useFormContext, Controller } from 'react-hook-form'
const FormInput = ({ name, label, required }) => {
const { control } = useFormContext()
return (
<Grid item xs={12} sm={6}>
<Controller
control={control}
name={name}
render = {({ field})=> (
<TextField
fullWidth
label={label}
required
/>
)}
/>
</Grid>
)
}
export default FormInput
It now requires a render props, try this on MUI:
<Controller
render={({ field }) => (
<TextField {...field} label={label} required={required}/>)}
control={control}
fullWidth
name={name}
/>

How can i change the both value change and function call in a single onChange

Here is the code, and i want to call apifetcher at the same time when the value of the city changes.how to do that?? is it possible
The value of the city should replace the 'q' value. And after that both the city and the API are passing to an another file.what should I add or remove.
import React, { useState } from "react";
import Cities from "./citylist";
import Autocomplete from "#material-ui/lab/Autocomplete";
import TextField from "#material-ui/core/TextField";
import Content from "./content";
const SearchBar = () => {
const [city, setcity] = useState("");
const [api, setapi] = useState(
`http://api.openweathermap.org/data/2.5/forecast?q=Kurunegala,LK& mode=json&appid=5c4420d5c8a61c16e5ee37e4ca265763`
);
console.log(city);
Content(city, api);
const apiFtecher = () => {
return setapi(
`http://api.openweathermap.org/data/2.5/forecast?q=${city},LK&mode=json&appid=5c4420d5c8a61c16e5ee37e4ca265763`
);
};
return (
<div style={{ width: 300 }}>
<Autocomplete
freeSolo
id="free-solo-2-demo"
disableClearable
options={Cities.map((option) => option.name)}
renderInput={(params) => (
<TextField
{...params}
label="city"
margin="normal"
variant="outlined"
InputProps={{ ...params.InputProps, type: "search" }}
onChange={(e) => setcity(e.target.value)}
onBlur={(e) => setcity(e.target.value)}
/>
)}
/>
</div>
);
};
export default SearchBar;
There doesn't seem to be a need for the city state variable.
To call apiFtecher[sic] on every change of the input, you would do something like this:
const apiFtecher = e => {
const city = e.target.value;
return (
setapi(`http://api.openweathermap.org/data/2.5/forecast?q=${city},LK&mode=json&appid=5c4420d5c8a61c16e5ee37e4ca265763`)
);
}
And update the element to:
<TextField
{...params}
label="city"
margin="normal"
variant="outlined"
InputProps={{ ...params.InputProps, type: 'search' }}
onChange={apiFtecher}
/>

Categories