简体   繁体   English

MUI 时间选择器不在输入字段中显示格式化的时间值

[英]MUI Time picker doesn't show formatted time value in input field

My main objective is to use MUI time picker with yup validation and react-hook-form but the problem I'm facing is that when I choose time from time picker the value is not updated in the text field as shown below.我的主要目标是使用带有 yup 验证和 react-hook-form 的 MUI 时间选择器,但我面临的问题是,当我从时间选择器中选择时间时,文本字段中的值不会更新,如下所示。 主要问题图片

I have used type 'TIME' for my database so I need the input to be formatted.我为我的数据库使用了“TIME”类型,所以我需要对输入进行格式化。 However, the working one (End Time) returns time with date which is not accepted in the database.但是,工作时间(结束时间)返回数据库中不接受的带有日期的时间。 The difference is shown in the console log below.差异显示在下面的控制台日志中。

day: "tuesday"
end_time: "Tue May 31 2022 05:27:00 GMT+0545 (Nepal Time)"
start_time: "05:29:00"
subject: "Account"
[[Prototype]]: Object

Here is my source code:这是我的源代码:

import React, { useState, useEffect } from 'react'
import { Button, Box, Card, CardContent, TextField, Typography, CardHeader, Grid, MenuItem } from '@mui/material';
import { useNavigate, useParams } from 'react-router-dom';
import { useForm, Controller } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import * as Yup from 'yup';
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
import { TimePicker, LocalizationProvider } from '@mui/x-date-pickers';
import { format, parseISO } from 'date-fns';
import TimeTableService from '../../../services/timetable.service';
import SubjectService from '../../../services/subject.service';

const TimetableForm = () => {
    const { id } = useParams();
    const validationSchema = Yup.object().shape({
        day: Yup.string().required("Day is required"),
        start_time: Yup.string().required("Start time is required"),
        end_time: Yup.string().required("End time is required"),
        subject: Yup.string().required("Subject is required"),
    });
    const {
        control,
        handleSubmit,
        setValue,
        formState: { errors }
    } = useForm({ resolver: yupResolver(validationSchema), mode: 'onChange' });
    const initialTimeTableState = {
        id: null,
        day: '',
        start_time: '',
        end_time: '',
        Subject: {},
    }
    const [currentTimeTable, setCurrentTimeTable] = useState(initialTimeTableState);
    const [subjects, setSubjects] = useState([]);
    const [editMode, setEditMode] = useState(false);
    const [loading, setLoading] = useState(false);
    const [message, setMessage] = useState("");
    const navigate = useNavigate();

    useEffect(() => {
        SubjectService.getAllSubjects().then(response => {
            setSubjects(response.data);
        })
        if (id) {
            TimeTableService.getTimeTable(id).then(response => {
                const timeTable = response.data;
                const fields = ['day', 'start_time', 'end_time'];
                fields.forEach(field => setValue(field, timeTable[field]));
                setValue('subject', timeTable.Subject.name);
                setCurrentTimeTable(timeTable);
                setEditMode(true);
            })
        }
    }, [id, setValue]);

    const onError = (errors, e) => console.log(errors, e);
    const onSubmit = (data) => {
        const start_time = data.start_time;
        // const start = format(start_time, "hh:mm a");
        console.log(start_time, data);
        // setMessage("");
        // setLoading(true);
        // if (editMode) {
        //     TimeTableService.updateTimeTable(id, data).then(() => {
        //         setLoading(false);
        //         navigate("/dashboard/timetable");
        //     }, (error) => {
        //         const resMessage = (error.response && error.response.data && error.response.data.message) || error.message || error.toString();
        //         setLoading(false);
        //         setMessage(resMessage);
        //     });
        // } else {
        //     TimeTableService.createTimeTable(data).then(() => {
        //         setLoading(false);
        //         navigate("/dashboard/timetable");
        //         window.location.reload();
        //     }, (error) => {
        //         const resMessage = (error.response && error.response.data && error.response.data.message) || error.message || error.toString();
        //         setLoading(false);
        //         setMessage(resMessage);
        //     });
        // }
    }

    const days = [
        {
            title: "Sunday",
            value: "sunday"
        },
        {
            title: "Monday",
            value: "monday"
        },
        {
            title: "Tuesday",
            value: "tuesday"
        },
        {
            title: "Wednesday",
            value: "wednesday"
        },
        {
            title: "Thursday",
            value: "thursday"
        },
        {
            title: "Friday",
            value: "friday"
        },
        {
            title: "Saturday",
            value: "saturday"
        }
    ];

    return (
        <Box sx={{ mt: 3 }}>
            <Card>
                <Box sx={{ minWidth: 1050 }}>
                    <CardHeader
                        title={id ? "Edit Time Table" : "Add Time Table"}
                    />
                    <CardContent>
                        {message && (<Typography variant='body2' color='error' >{message}</Typography>)}
                        <Grid container spacing={2}>
                            <Grid item md={4} xs={6}>
                                <LocalizationProvider dateAdapter={AdapterDateFns}>
                                    <Controller
                                        control={control}
                                        name="start_time"
                                        defaultValue={currentTimeTable.start_time || ""}
                                        render={({ field }) => (
                                            <TimePicker
                                                {...field}
                                                inputFormat="HH:mm:ss"
                                                mask='__:__:__'
                                                label="Start Time"
                                                onChange={(time) => {
                                                    const formattedTime = format(time, "HH:mm:ss");
                                                    field.onChange(formattedTime);
                                                }}
                                                renderInput={(params) => (
                                                    <TextField
                                                        {...params}
                                                        fullWidth
                                                        label="Start Time"
                                                        variant="outlined"
                                                        margin='dense'
                                                        color='dark'
                                                        size='small'
                                                        error={errors.start_time ? true : false}
                                                    />
                                                )}
                                            />
                                        )}
                                    />
                                </LocalizationProvider>
                                <Typography variant="body2" color="error">
                                    {errors.start_time?.message}
                                </Typography>
                            </Grid>
                            <Grid item md={4} xs={6}>
                                <LocalizationProvider dateAdapter={AdapterDateFns}>
                                    <Controller
                                        control={control}
                                        name="end_time"
                                        defaultValue={currentTimeTable.end_time || ""}
                                        render={({ field }) => (
                                            <TimePicker
                                                {...field}
                                                label="End Time"
                                                // onChange={(time) => field.onChange(time)}
                                                renderInput={(params) => (
                                                    <TextField
                                                        {...params}
                                                        fullWidth
                                                        label="End Time"
                                                        variant="outlined"
                                                        margin='dense'
                                                        color='dark'
                                                        size='small'
                                                        error={errors.end_time ? true : false}
                                                    />
                                                )}
                                            />
                                        )}
                                    />
                                </LocalizationProvider>
                                <Typography variant="body2" color="error">
                                    {errors.end_time?.message}
                                </Typography>
                            </Grid>
                            <Grid item md={4} xs={6}>
                                <Controller
                                    control={control}
                                    name='subject'
                                    defaultValue={currentTimeTable.Subject.name || ""}
                                    render={({ field }) => (
                                        <>
                                            <TextField
                                                {...field}
                                                select
                                                fullWidth
                                                label='Subject'
                                                variant='outlined'
                                                margin='dense'
                                                color='dark'
                                                size='small'
                                                error={errors.subject ? true : false}
                                            >
                                                {subjects.map(subject => (
                                                    <MenuItem key={subject.id} value={subject.name}>{subject.name}</MenuItem>
                                                ))}
                                            </TextField>
                                        </>
                                    )}
                                />
                                <Typography variant="body2" color="error">
                                    {errors.subject?.message}
                                </Typography>
                            </Grid>
                            <Grid item md={4} xs={6}>
                                <Controller
                                    control={control}
                                    name='day'
                                    defaultValue={currentTimeTable.day || ""}
                                    render={({ field }) => (
                                        <>
                                            <TextField
                                                {...field}
                                                select
                                                fullWidth
                                                label='Day'
                                                variant='outlined'
                                                margin='dense'
                                                color='dark'
                                                size='small'
                                                error={errors.day ? true : false}
                                            >
                                                {days.map(day => (
                                                    <MenuItem key={day.title} value={day.value}>{day.title}</MenuItem>
                                                ))}
                                            </TextField>
                                        </>
                                    )}
                                />
                                <Typography variant="body2" color="error">
                                    {errors.day?.message}
                                </Typography>
                            </Grid>
                        </Grid>
                        <Button
                            variant='outlined'
                            color={(loading) ? 'warning' : 'success'}
                            sx={{ my: 1.5 }}
                            disabled={(loading) ? true : false}
                            onClick={handleSubmit(onSubmit, onError)}>
                            {(loading) ? "Loading..." : "Submit"}
                        </Button>
                    </CardContent>
                </Box>
            </Card>
        </Box>
    )
}

export default TimetableForm

Is there any way to fix this?有没有什么办法解决这一问题? Thanks.谢谢。

NOTE: TimetableForm component is rendered by using <Outlet /> of react route.注意: TimetableForm组件是使用 react 路由的<Outlet />渲染的。

EDIT: This is the codeSandbox link : https://codesandbox.io/s/gifted-roentgen-94bnpq编辑:这是 codeSandbox 链接: https ://codesandbox.io/s/gifted-roentgen-94bnpq

The problem is in this line of code :问题出在这行代码中:

onChange={(time) => {
          const formattedTime = format(time, "HH:mm:ss");
          field.onChange(formattedTime);
}}

That's beacause format(time, "HH:mm:ss") returns a String , but the time picker expects a Date object.这是因为format(time, "HH:mm:ss")返回一个String ,但时间选择器需要一个Date对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM