Setting "DD/MM/YYYY" format in MUI - reactjs

In my MUI form I'm using DatePicker to select dates for departure and return of users. But when I used .toLocaleDateString() it set my dates in mm-dd-yyyy format. But I wanted to set them as dd-mm-yyyy format. For that I've passed 'en-GB' as parameter in .toLocaleDateString(). But in the DatePicker TextField it shows a red border Like this and the pre-defined date (from the state) are also gone. Without the parameter it shows This which is the mm-dd-yyyy format. From the similar previous questions I even tried it through moment package and set the dt variable as moment(new Date()).format("DD/MM/YYYY") but it is still showing red border around the text field. I know this question was asked a lot of times before and I went through all of them and got no solution.
Date picker
const dt = new Date().toLocaleDateString();
console.log(dt);
const [formData, setFormData] = useState({
from: "",
to: "",
depart: dt,
return: dt,
noOfPassenger: 1,
tripType: "Return",
});
{/* App component */}
<div className="dates">
<LocalizationProvider dateAdapter={AdapterDateFns}>
<DatePicker
label="Departure Date"
disablePast
onChange={(e) =>
setFormData({
...formData,
depart: e.toLocaleDateString(),
})
}
value={formData.depart}
renderInput={(params) => <TextField {...params} required />}
/>
</LocalizationProvider>
</div>

In my case I used a DateRangePicker, but it's the same across all pickers.
Just set the inputFormat like here:
<DateRangePicker
startText={t`From`}
endText={t`To`}
value={dateValue}
inputFormat="dd.MM.yyyy"
onChange={(newValue) => {
setDateValue(newValue);
console.log(newValue);
}}
renderInput={(startProps, endProps) => (
<React.Fragment>
<TextField {...startProps} />
<TextField {...endProps} />
</React.Fragment>
)}
/>

Emanuel Avram has already given a good answer. I will just add.
The value (date) of the component must have the same format defined internally, so it's no use using "toLocaleString()" without changing the internal format. Use the "inputFormat" property.
// "dd" = "Su", "Mo", ..., "Sa"
// "DD" = "01", "02", ..., "31"
inputFormat="dd/MM/YYYY" // Tu/09/2022
inputFormat="DD/MM/YYYY" // 09/13/2022
<DatePicker
label="Departure Date"
inputFormat="DD-MM-YYYY" // 13-09-2022
onChange={(e) =>
setFormData({
...formData,
depart: e.toLocaleDateString(),
})
}
value={formData.depart}
renderInput={(params) => <TextField {...params} required />}
/>

Related

Convert DatePicker value in material ui

I have a form with a datePicker input from material-ui
When I pick a date and submit my form, if I console.log my data I will receive 'Tue Jan 10 2023 10:31:48 GMT+0100 (Central European Standard Time)' i want to received '01/11/2023'
I would like to format the data received.
Here my DatePicker :
const [deadLine, setDeadLine] = useState(new Date());
<Controller
name="deadLine"
defaultValue={deadLine}
control={control}
render={({ field: { onChange, ...restField } }) => (
<LocalizationProvider dateAdapter={AdapterDateFns}>
<DatePicker
label="Request Date"
onChange={(event) => {
console.log(event);
onChange(event);
setDeadLine(event);
}}
renderInput={(params) => <TextField {...params} />}
{...restField}
/>
</LocalizationProvider>
)}
/>
I have already tried :
To Use "format="dd-MM-yyyy"" from material-ui, but it only change the
visual not the data received.
To use moment with
setDeadLine(moment(event.target.value).format('MM/DD/YYYY'));,
still received the initial value.
To know : I am using react-hook-form
First of all to use moment you should wrap you DatePicker with moment Adapter:
<LocalizationProvider dateAdapter={AdapterMoment}> more also, onChange return the value you shouldn't access it with event.target.value, but you have directly the value with moment(value).format('DD/MM/YYYY') and of course don't forget to import Adapter Moment - import { AdapterMoment } from '#mui/x-date-pickers/AdapterMoment';
It should look like that:
<LocalizationProvider dateAdapter={AdapterMoment}>
<DatePicker
label="Request Date"
onChange={(value) => {
setDeadLine(moment(value).format('DD/MM/YYYY'));
}}
renderInput={(params) => <TextField {...params} />}
{...restField}
/>
</LocalizationProvider>

DatePicker using React Hook Form not displaying format correctly

I'm using DatePicker in side a react hook form.
I'm able to get my form to display the Date I pick but it's not in the format I'm expecting.
The text box the is correct August 19, but when I try to get it to display using
it comes back at as this format 2022-09-19T23:51:47.000Z
I'm not sure what I'm missing as i'm pretty stump at the moment on what needs for it to display correctly.
<LocalizationProvider dateAdapter={AdapterDateFns}>
<Controller
name="Date"
control={control}
defaultValue=""
rules={{
required: { value: true, message: "Date is required" },
}}
render={({ field }) => (
<DatePicker
openTo="month"
views={["month", "day"]}
label="month and date"
value={field.value}
onChange={(e, data) =>
field.onChange(data);
}
inputFormat="MMMM dd"
renderInput={(params) => (
<TextField {...params} helperText={null} />
)}
{...field}
/>
)}
/>
</LocalizationProvider>
If you're using date-fns you can do this with the ISOString:
format(new Date('2022-09-19T23:51:47.000Z'), 'MMMM DD', { locale: 'US' });
It would return:
September 19

ReactJS: Firebase timestamp converting with MobileDatePicker

Am using MobileDatePicker to set a date (chosen by user) and saving that as a timestamp within Firebase.
For the adding of the record it is working fine:
<MobileDatePicker
label={"Date From"}
inputFormat="dd/MM/yyyy"
closeOnSelect={true}
value={datefrom}
minDate={new Date()}
views={['day']}
onChange={(newValue) => {
setDateFrom(format(newValue, 'MM/dd/yyyy')); }}
renderInput={(params) => <TextField variant="outlined" {...params} fullWidth />}
/>
firebase
.firestore()
.collection("collection")
.doc(tripid)
.set({
DateFrom: firebase.firestore.Timestamp.fromDate(new Date(datefrom))
...
When they update the collection, this is where I am having problems - I convert the timestamp into a date that MobileDatePicker understands and displays properly but am having issues then allowing the user to update the date and re-save it back as a timestamp field.
<MobileDatePicker
style={{ width: '100%' }}
label={"Date From"}
inputFormat="dd/MM/yyyy"
disablePast
views={['day']}
value={item.DateFrom == '' ? item.DateFrom : new Date(item.DateFrom.toDate()).toISOString()}
onChange={handleChangeFrom}
renderInput={(params) => <TextFields {...params} fullWidth />}
/>
const handleChangeFrom = (event) => {
setItem({ ...item, DateFrom: firebase.firestore.Timestamp.fromDate(new Date(item.DateFrom)) });
settogles(true)
};
I get the error: RangeError: Invalid time value
I think it has something to do with the handleChangeFrom function (so it is not assigning a time) ... but have no idea how to then convert it back to a timestamp that firebase understands.

How to set the placeholder text of the MUI DatePicker?

How can I set the placeholder text of the MUI DatePicker. The text that is displayed when deleting the text in the input field. I want to set the text to "tt.mm.jjjj" and I always the following error message:
Format string contains an unescaped latin alphabet character `j`
Sandbox
<DatePicker
inputFormat="tt.mm.jjjj"
label="Basic example"
value={value}
onChange={(newValue) => {
setValue(newValue);
}}
renderInput={(params) => <TextField placeholder="tt.mm.jjjj" {...params} />}
/>
This is how you reset the placeholder of the TextField inside the DatePicker. The reason it doesn't work is because it is overridden by the params.inputProps provided by the DatePicker itself based on the inputFormat:
<DatePicker
{...}
inputFormat="tt.mm.yyyy"
renderInput={(params) => {
console.log(params);
return (
<TextField
{...params}
inputProps={{
...params.inputProps,
placeholder: "tt.mm.jjjj"
}}
/>
);
}}
/>

React Hook Form with datepicker Range doesn't pick date

I got the following datepickers.
For the Start Date:
<Controller
as={
<DatePicker
selected={travelRoute?.dateStart || new Date()}
selectsStart
startDate={travelRoute?.dateStart}
endDate={travelRoute?.dateEnd}
inline
/>
}
control={control}
rules={{ required: true }}
valueName="selected"
onChange={date => handleStartDateOnChange(date)}
name="dateStart"
placeholderText="Select date"
defaultValue={null}
/>
For the End Date:
<Controller
as={
<DatePicker
name="dateEnd"
selected={travelRoute?.dateEnd || new Date()}
onChange={date => handleEndDateOnChange(date)}
selectsEnd
startDate={travelRoute?.dateStart}
endDate={travelRoute?.dateEnd}
minDate={travelRoute?.dateStart}
inline
/>
}
control={control}
rules={{ required: true }}
valueName="selected"
onChange={date => handleEndDateOnChange(date)}
name="dateEnd"
placeholderText="Select date"
defaultValue={null}
/>
Do I need to add the datepicker props to the datepicker component or to the Controller Component?
The start Datepicker doesn't select the date and the end Datepicker doesn't change the startdate and isn't displaying the range.
I'm saving the data into the travelRoute state with setTravelRoute which is happening in the handleOnChange functions.
EDIT:
Added onChange handler:
const handleStartDateOnChange = date => {
setTravelRoute(prevState => ({
...prevState,
dateStart: date
}))
};
const handleEndDateOnChange = date => {
setTravelRoute(prevState => ({
...prevState,
dateEnd: date
}))
};
Ciao, you are using the wrong approach to customize your onChange event in DatePicker. And onChange event on Controller can't work neihter. Because in this case, you don't have to use as= syntax, but render= syntax like:
<Controller
render={({ onChange }) => (
<DatePicker
...
onChange={date => handleStartDateOnChange(date)}
/>
)}
...
/>
So your code becomes:
Start Date
<Controller
render={({ onChange }) => (
<DatePicker
selected={travelRoute?.dateStart || new Date()}
selectsStart
startDate={travelRoute?.dateStart}
endDate={travelRoute?.dateEnd}
inline
onChange={date => handleStartDateOnChange(date)}
/>
)}
control={control}
rules={{ required: true }}
valueName="selected"
name="dateStart"
placeholderText="Select date"
defaultValue={null}
/>
End Date
<Controller
render={({ onChange }) => (
<DatePicker
name="dateEnd"
selected={travelRoute?.dateEnd || new Date()}
onChange={date => handleEndDateOnChange(date)}
selectsEnd
startDate={travelRoute?.dateStart}
endDate={travelRoute?.dateEnd}
minDate={travelRoute?.dateStart}
inline
/>
)}
control={control}
rules={{ required: true }}
valueName="selected"
name="dateEnd"
placeholderText="Select date"
defaultValue={null}
/>
Here a working example.
Note: I don't know why DatePicker in codesandbox looks so ugly. Could be the Controller because in this other codesandbox looks good.
I have had a different approach to the solution of this issue and wanted to share it.
I answered some related issue in the following post: https://stackoverflow.com/a/72585781/19320134
Anyway, one way to make the code more reusable is to put these controllers in separate files, so that only the function name is imported when calling them.
export const DateRange = ({ name, control, label }) => {
const [dateRange, setDateRange] = useState([null, null]);
const [startDate, endDate] = dateRange;
return (
<Controller
//is a prop that we get back from the useForm Hook and pass into the input.
control={control}
//is how React Hook Form tracks the value of an input internally.
name={name}
//render is the most important prop; we pass a render function here.
render={({
//The function has three keys: field , fieldState, and formState.
field, // The field object exports two things (among others): value and onChange
}) => (
<>
<DatePicker
selectsRange={true}
startDate={startDate}
endDate={endDate}
onChange={(e) => {
setDateRange(e);
field.onChange(e);
}}
isClearable={true}
className="form-control"
/>
</>
)}
rules={{
required: `The ${label} field is required`,
}}
/>
And you can call it in the necesary file like this
import { useForm, Controller, FormProvider } from "react-hook-form";
import {DateRange} from "./your file !"
const defaultValues = {
dateRange: [],
};
export default function ComponentUsingDateRange() {
const methods = useForm({
defaultValues,
mode: "onChange",
});
const { register, handleSubmit, control, setValue } = methods;
return(
<>
<FormProvider {...methods}>
<DateRange
control={control}
name="dateRange"
label="Range of dates"
/>
</FormProvider>
</>
);
}

Resources