defaultValue of showTime attribute in antd datePicker couldn't set the time - reactjs

I'm using ant design for my react hook based development. I am retrieving date from database over a network call and the date retrieved from database is look like "2020-09-01T05:02:00.000+0000". It is a string. I have to parse this date and show the date value and time value through antd datePicker in my page. Though I've success with setting up date part but I'm stuck with setting up the time. Here is my code,
###########
Here is my datepicker
###########
<DatePicker
name="Campaign-date"
defaultValue={moment(formData['Campaign-date'].split('T')[0])}
showTime={{
defaultValue: moment(formData['Campaign-date'].split('T')[1],'HH:mm'),
format: 'HH:mm'
}}
format={'YYYY-MM-DD HH:mm'}
style={{ width: '100%' }}
onChange={handleDateChange}
/>
##########################
Here is my handleDateChange function
##########################
const handleDateChange = date => {
setFormdata({
...formData,
'Campaign-date': date
.format('YYYY-MM-DD HH:mm')
.split(' ')
.join('T')
});
};
formData['Campaign-date'] is the date retrieved from the database. I feel the showTime attribute is not working as expected. I want to get a result of "05:02" but instead the value shown is, "00:00".
I have tried different variation in showTime such as,
defaultValue: moment('05:02','HH:mm'),
//or
defaultValue: moment(formData['Campaign-date'],'HH:mm')
//or
defaultValue: moment(formData['Campaign-date'].split('T')[1].split('.),'HH:mm')
but nothing is working. It is always setting the value as "00:00".
And I have no problem with my onChange functionality. It is working perfect. The date/time change code wise working as expected. It is just the view on my page is not showing correct time.
I'm really stuck with. Any help therefore, is much appreciated.

Ant Design DatePicker:
(sandbox)
import React from "react";
import ReactDOM from "react-dom";
import { DatePicker, Space } from "antd";
import moment from "moment";
import "./index.css";
import "antd/dist/antd.css";
const initialState = {
data1: "form field",
data2: "form field 2",
"Campaign-date": "2020-09-01T05:02:00.000+0000"
};
function FormComponent() {
const [formData, setFormData] = React.useState(initialState);
console.log(formData);
function onChange(value, dateString) {
if (value) {
setFormData({
...formData,
"Campaign-date": value.toISOString(true)
});
}
//console.log("Selected Time: ", value); //Moment object
//console.log("Formatted Selected Time: ", dateString); //String
}
return (
<Space direction="vertical" size={12}>
<DatePicker
name="Campaign-date"
defaultValue={moment(formData["Campaign-date"], "YYYY/MM/DD HH:mm")}
format={"YYYY/MM/DD HH:mm"}
showTime={{ format: "HH:mm" }}
onChange={onChange}
/>
<div style={{ marginTop: 16 }}>
Selected Date:{" "}
{formData["Campaign-date"]
? moment(formData["Campaign-date"]).format("YYYY-MM-YY HH:mm")
: "None"}
</div>
</Space>
);
}
ReactDOM.render(<FormComponent />, document.getElementById("container"));
If you are using react-datepicker 2.0 or up, you need to use a javascript Date object. Here is a working setup.
function parseISOString(s) {
var b = s.split(/\D+/);
return new Date(Date.UTC(b[0], --b[1], b[2], b[3], b[4], b[5], b[6]));
}
const isoString = '2020-09-01T05:02:00.000+0000';
const dateFromISOString = parseISOString(isoString);
<DatePicker
selected={dateFromISOString}
dateFormat="dd/MM/yyyy HH:mm"
showTimeSelect
timeFormat="HH:mm"
timeIntervals={15}
placeholderText="Select date"
onChange={handleChange}
/>
Overview
The string you are receiving from the database is an ISO date string.
You can use moment.js to easily parse it or parse it manually and create a new Date object from it.
Here is a snippet illustrating both. The Date example uses this answer: Change ISO Date String to Date Object - JavaScript
const isoString = "2020-09-01T05:02:00.000+0000"
// with Moment
console.log("With Moment");
const timeFromMoment = moment(isoString).format("HH:mm");
console.log(timeFromMoment);
// with Date
console.log("With Date");
// https://stackoverflow.com/questions/27012854/change-iso-date-string-to-date-object-javascript
function parseISOString(s) {
var b = s.split(/\D+/);
return new Date(Date.UTC(b[0], --b[1], b[2], b[3], b[4], b[5], b[6]));
}
const dateFromISOString = parseISOString(isoString);
console.log(dateFromISOString);
// return Local adusted time
const localHours = dateFromISOString.getHours();
console.log(localHours);
// return UTC time
const utcHours = dateFromISOString.getUTCHours();
console.log(utcHours);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.27.0/moment.min.js"></script>

<DatePicker
name="Campaign-date"
defaultValue={moment(formData['Campaign-date'].split('T')[0])}
showTime={{
defaultValue: moment(formData['Campaign-date'].split('T')[1].split('.')[0],'HH:mm:ss'),
format: 'HH:mm:ss'
}}
format={'YYYY-MM-DD HH:mm'}
style={{ width: '100%' }}
onChange={handleDateChange}
/>

Related

Validating a MUI Datepicker with YUP in a react-hook-form

I have a date picker that needs to validate the following scenarios:
It is a required field and cannot be left blank
The date must be later minDate (21 days from today )
The date must be earlier than six months from minDate
The validation schema I came up with looks as follows, which, works unexpectedly.
import * as yup from 'yup'
import { addDays, addMonths, format} from 'date-fns'
const today = Date.now()
const minDate = addDays(today, 21)
const maxDate = addMonths(minDate, 6)
const schema = yup.object().shape({
Date: yup
.date()
.min(minDate, `Date must be after ${format(minDate,'MM/dd/yyyy')}`)
.max(maxDate, `Date must be before ${format(maxDate, 'MM/dd/yyyy') }`)
.typeError("Date is required")
})
What do I mean by it works unexpectedly
When you click the submit button for the first time, the
typeError() message is display.(Expected behavior)
Then, if you selected a date from by clicking on the calendar icon,
the date gets displayed and the error disappear. (Expected behavior)
Finally, if I manually clear the selected day the min() error
message gets displayed. (make sense but is not what I expected)
It makes sense because, as the date gets transformed with every keystroke, the min() the error message is triggered, but eventually, the date is not valid and its value becomes null.
Question: So, at this point should the typeError() message be displayed?
Date picker code
import React, { useState } from 'react'
import { Controller } from 'react-hook-form'
import TextField from '#mui/material/TextField'
import { AdapterDateFns } from '#mui/x-date-pickers/AdapterDateFns'
import { LocalizationProvider } from '#mui/x-date-pickers/LocalizationProvider'
import { DesktopDatePicker } from '#mui/x-date-pickers/DesktopDatePicker'
import { addDays, addMonths, format, isValid } from 'date-fns'
const Calendar = ({ control, name, label, error, helperText, ...rest }) => {
const today = Date.now()
const [value, setValue] = useState(null);
return (
<LocalizationProvider dateAdapter={AdapterDateFns}>
<Controller
name={name}
control={control}
render={({ field }) => (
<DesktopDatePicker
label={label}
value={value}
minDate={addDays(today, 21)}
maxDate={addMonths(addDays(today, 21), 6)}
onChange={(newValue) => {
if (isValid(newValue))
{
field.onChange(format(newValue, 'MM/dd/yyyy'))
setValue(newValue)
} else
{
setValue(newValue)
}
}}
renderInput={(params) =>
<TextField
margin='normal'
helperText={helperText}
{...params}
{...rest}
error={error}
/>
}
/>
)}
/>
</LocalizationProvider>
)
}
export default Calendar
CHECK WORKING EXAMPLE >

Get React DatePicker date value in onChange

I'm using react-datepicker, and I'm unable to get the actual date in onChange.
This is my component :
import DatePicker from "react-datepicker";
const DatePick = () => {
return (
<DatePicker
locale="fr"
dateFormat="dd/MM/yyyy"
onChange={(date) => {
console.log(date);
}}
/>
);
};
export default DatePick;
In console.log I'm getting this kind of string Thu Dec 09 2021 00:00:00 GMT+0100 (heure normale d’Europe centrale).
I need to get the date as dd-MM-yyyy in onChange or a date that I can format and use later in a form and submit its value.
Use Below code , it will work like a charm
const [Cdate, setDate] = useState(new Date().toLocaleDateString('fr-FR'));
return (
<>
<DatePicker
dateFormat="dd/MM/yyyy"
value={Cdate}
onChange={(date) => {
const d = new Date(date).toLocaleDateString('fr-FR');
console.log(d);
setDate(d);
}}
/>
</>
);
stackblitz link: https://stackblitz.com/edit/react-nov8it?file=src/App.js
You can use the Date object, to format the date as you would like. For instance :
onChange={(date) => {
const dateString = new Date(date).toLocaleDateString()
console.log(dateString)
}}
You will then get the date formated to your locale time zone. However, if you specified a different format in your DatePicker from your local timezone format, then you can specify it as a parameter for toLocaleDateString:
new Date(date).toLocaleDateString("fr-FR")

React Hooks selecting data to a date picker

I have a MUI date picker in my React app that I want to use with serverside data.
I'm returning the correct data in my console log that I pass in my useState hook const [availableDate, setAvailableDate] = useState({}); and now want to pass the selected date into the picker:
returned JSON
const data = [
{
date: '05/05/21',
timeSlots: [
{
end: '11:00',
start: '12:00'
}
]
},
{
date: '05/05/24',
timeSlots: [
{
end: '13:00',
start: '14:00'
}
]
}
];
Date Picker
const [availableDate, setAvailableDate] = useState({});
const [filteredData, setFilteredData] = useState(availableDate);
//set current date as default
var curr = new Date();
function setDate(dat) {
let datt = {
date: {// ... returend date},
start: '11:40',
end: '13:00',
};
service.stepDate.setCvData(datt);
}
curr.setDate(curr.getDate());
var date = curr.toISOString().substr(0, 10);
Date Picker
I tried mapping the array data in my date picker but this just returns multiple pickers.
{availableDates.map((index) => (
<div className="calendarWrapper">
<form noValidate>
<TextField
key={index.id}
minDate={today}
id="date"
type="date"
onChange={setDate}
defaultValue={date}
/>
</form>
</div>
))}
How do I extract the selected date ex: date: "2021/05/24" from the json and pass it into my setDate() function?
First of all, onChange interface is the following
onChange(e) {
// e.target.value
}
so you won't be able to get your date from e directly.
Also date is an object, which can't be {} initially, null could be one option, or new Date().

How to create a simple formik field for entering date and time?

I am trying to create a very simple formik field for entering date and time. The requirements are:
The field's value should be a JavaScript Date.
The field should allow entering free-form text in an input field and convert it to a Date on blur events.
The field should display an error if the entered string cannot be converted to a valid date.
If the form is reset, the field should show the initial value of the date.
While I was able to satisfy requirements 1 & 2 quite easily, I am having trouble with requirements 3 & 4. I think part of the problem is that I am storing the raw text of the input field in internal state. However, I can't think of another way. Is there a better pattern?
Here's my CodeSandbox. Please see the sections marked with "Issue 1" & "Issue 2"
Try this solution:
Use Field component from Formik to bind your custom component
<Field name="date" timezone={DefaultTz} component={DateTimeField} />
Use form property from Field to display errors
{form.errors.date ? (
<div className="text-danger">{form.errors.date}</div>
) : null}
Use spread operator to bind formik fields and your custom blur which converts the date
<input
className="form-control"
placeholder={format}
{...{ ...field, onBlur }}
/>
Altogether it looks like this
import React from "react";
import { DateUtils } from "#react-force/date-utils";
export interface DateTimeFieldProps extends React.InputHTMLAttributes<Date> {
field: any;
form: any;
timezone: string;
format?: string;
}
export const DateTimeField = ({
field,
form,
timezone,
format = "YYYY-MM-DD hh:mm A",
}: DateTimeFieldProps) => {
const onBlur = () => {
try {
form.setValues({
date: DateUtils.createDate(field.value, format, timezone),
});
} catch (error) {
console.log(error);
}
};
return (
<React.Fragment>
<input
className="form-control"
placeholder={format}
{...{ ...field, onBlur }}
/>
{form.errors.date ? (
<div className="text-danger">{form.errors.date}</div>
) : null}
</React.Fragment>
);
};
The working version is here

Access data from an array of dates

My application can get data from user. For this i have different inputs. One of my inputs is date Picker.
<Form.Item name="Picker" label="date">
<RangePicker
showTime={{ format: "HH:mm" }}
format="YYYY-MM-DD HH:mm"
onChange={onChange2}
onOk={onOk}
/>
</Form.Item>
The issue appear when i try to access data after clicking on submit button. In console i have all data from each input, but from RangePicker, the data is not structured, and i get:
Picker: Array[2]
0: Moment
1: Moment
The problem is that i can access this array, and display on fron end. How to do this?
link to my app: https://codesandbox.io/s/form-methods-ant-design-demo-kbwgk
Try this
import moment from 'moment'
const onFinish = values => {
const startDate = moment(values.Picker[0]).format("YYYY-MM-DD HH:mm");
const endDate = moment(values.Picker[1]).format("YYYY-MM-DD HH:mm");
console.log(startDate, endDate)
};
I got it,
on your rangepicker use
onFinish instead of onOk
<RangePicker
showTime={{ format: "HH:mm" }}
format="YYYY-MM-DD HH:mm"
onChange={onChange2}
onFinish={onFinish}
/>
working as specified
you press Ok twice , so the first onOk still doesnt include the second part of the range
sorry for not giving professional answer
Since you are getting it as an array of moment objects,try using moment js for formatting the moment js according to your needs
https://codesandbox.io/s/form-methods-ant-design-demo-sy4uq
function onOk(value) {
const start = moment(value[0]).format("YYYY-MM-DD HH:mm:ss");
const end = moment(value[1]).format("YYYY-MM-DD HH:mm:ss");
console.log(start, end);
}
const onFinish = values => {
const start = moment(values.Picker[0]).format("YYYY-MM-DD HH:mm:ss");
const end = moment(values.Picker[1]).format("YYYY-MM-DD HH:mm:ss");
console.log(start, end)
};

Resources