英文:
How to implement mui Timepicker with latest 6 version with formik
问题
我正在使用 MUI react Timepicker。
我想要使用 Formik 进行集成,并进行验证,但问题是表单的 initialValues 中没有绑定值。
const [initialValues, setInitialValues] = useState({
mondayFrom: "",
mondayTo: "",
});
const onSubmit = async (values: RegisterFormProps) => {
console.log({values})// 这里没有获得 mondayFrom: ""
}
<Formik initialValues={initialValues} enableReinitialize onSubmit={onSubmit}>
{({
values,
errors,
touched,
handleSubmit,
handleChange,
isSubmitting,
setFieldValue,
}) => (
<Form onSubmit={handleSubmit}>
<Field name="mondayFrom">
{(field) => (
<TimePicker
{...field}
ampm={false}
format="HH:mm"
slotProps={{
textField: {
label: "Monday From",
size: "small",
fullWidth: true,
},
}}
/>
)}
</Field>
</Form>
)}
</Formik>;
英文:
I am working with MUI react Timepicker.
And I want to integrate it using Formik with validation but the issue is the values are not getting bound in the initialValues of the form.
const [initialValues, setInitialValues] = useState({
mondayFrom: "",
mondayTo: "",
});
const onSubmit = async (values: RegisterFormProps) => {
console.log({values})//here not getting mondayFrom: ""
}
<Formik initialValues={initialValues} enableReinitialize onSubmit={onSubmit}>
{({
values,
errors,
touched,
handleSubmit,
handleChange,
isSubmitting,
setFieldValue,
}) => (
<Form onSubmit={handleSubmit}>
<Field name="mondayFrom">
{(field) => (
<TimePicker
{...field}
ampm={false}
format="HH:mm"
slotProps={{
textField: {
label: "Monday From",
size: "small",
fullWidth: true,
},
}}
/>
)}
</Field>
</Form>
)}
</Formik>;
答案1
得分: 2
你的代码几乎正确,但存在两个问题。
- 解构字段。
- 存在一个已知问题,其中指出
> DateTime选择器未设置与初始值相同类型的数据。DateTime选择器发送包含完整字符串格式的日期时间的属性的对象。
通过将onChange
添加到field
的onChange
属性来解决此问题。下面的代码与你的代码非常相似,只需应用这些修复。
function App() {
const [initialValues, setInitialValues] = useState({
mondayFrom: "",
mondayTo: "",
});
const onSubmit = async (values: RegisterFormProps) => {
console.log({ values }) // 这里没有获得mondayFrom: ""
console.log(initialValues);
}
return (
<LocalizationProvider dateAdapter={AdapterDayjs} adapterLocale="en">
<div style={{ margin: 20, padding: 20 }}>
<Formik initialValues={initialValues} onSubmit={onSubmit}>
{({
handleSubmit, values, errors, touched, handleChange, isSubmitting, setFieldValue,
}) => (
<Form onSubmit={handleSubmit}>
<Field name="mondayFrom">
{({ field }) => {
return (
<TimePicker
ampm={false}
format="HH:mm"
slotProps={{
textField: {
label: "Monday From",
size: "small",
fullWidth: true,
},
}}
{...field}
onChange={(value) => {
setInitialValues({ mondayTo: initialValues.mondayTo, mondayFrom: value.toString() });
}}
/>
);
}}
</Field>
</Form>
)}
</Formik>
</div>
</LocalizationProvider>
);
}
更新:
正如Profer在评论中指出的,更好的onChange
方式是:
onChange={(value) => setFieldValue('mondayFrom', value.format("hh:mm"))}
英文:
Your code is almost correct, but there are two issues.
- Destructuring field.
- There's an open issue bug which states
> the DateTime picker doesn't set the same type of data as in the
> initialValues. DateTime picker sends an object containing a property
> which is the date time in full string format.
onChange
is added to overcome that bug by overriding field
's onChange
property.<br>
This code, very similar to your code just apply those fixes.<br>
function App() {
const [initialValues, setInitialValues] = useState({
mondayFrom: "", mondayTo: "",
});
const onSubmit = async (values: RegisterFormProps) => {
console.log({values})//here not getting mondayFrom: ""
console.log(initialValues)
}
return (<LocalizationProvider dateAdapter={AdapterDayjs} adapterLocale="en">
<div style={{margin: 20, padding: 20}}>
<Formik initialValues={initialValues} onSubmit={onSubmit}>
{({
handleSubmit,values, errors, touched, handleChange, isSubmitting, setFieldValue,
}) => (<Form onSubmit={handleSubmit}>
<Field name="mondayFrom">
{({field}) => {
return (<TimePicker
ampm={false}
format="HH:mm"
slotProps={{
textField: {
label: "Monday From", size: "small", fullWidth: true,
},
}}
{...field}
onChange={(value)=> {
setInitialValues({mondayTo: initialValues.mondayTo,mondayFrom: value.toString()})
}}
/>)}
}
</Field>
</Form>)}
</Formik>
</div>
</LocalizationProvider>);
}
Update:<br>
As pointed out by Profer in comments, a better way for onChange
is
onChange={(value) => setFieldValue('mondayFrom', value.format("hh:mm"))}
答案2
得分: 0
你还应该在TimePicker
上包括onChange
,这样每次更改它时,都会将新值设置为表单值:
<Formik
initialValues={initialValues}
enableReinitialize
onSubmit={onSubmit}>
{({ handleSubmit }) => (
<Form onSubmit={handleSubmit}>
<Field name="mondayFrom">
{({ field, form }) => (
<TimePicker
{...field}
ampm={false}
format="HH:mm"
slotProps={{
textField: {
label: "Monday From",
size: "small",
fullWidth: true
}
}}
onChange={(value) => {
form.setFieldValue(field.name, value);
}}
/>
)}
</Field>
</Form>
)}
</Formik>
这里有一个代码示例链接。
- 在示例中,我使用
dayjs
作为dateadapter
。
英文:
You should also include onChange
to the TimePicker
, so every time you change it, you set the new value to form values:
<Formik
initialValues={initialValues}
enableReinitialize
onSubmit={onSubmit} >
{({ handleSubmit }) => (
<Form onSubmit={handleSubmit}>
<Field name="mondayFrom">
{({ field, form }) => (
<TimePicker
{...field}
ampm={false}
format="HH:mm"
slotProps={{
textField: {
label: "Monday From",
size: "small",
fullWidth: true
}
}}
onChange={(value) => {
form.setFieldValue(field.name, value);
}}
/>
)}
</Field>
</Form>
)}
</Formik>
Here´s a code sample link.
* i'm using dayjs
as dateadapter
in the example.
答案3
得分: 0
以下是您要翻译的部分:
问题描述
问题在于,您正在使用的组件(TimePicker
)与其他组件的行为略有不同。
Formik 和 onChange 处理程序
Formik,您可能知道,使在 React 中开发表单变得更加容易。它通过维护所有输入组件的内部状态并在用户在input
组件中输入时调用onChange
处理程序来实现这一点。
所以通常情况下,当有输入更改时,onChange
处理程序将使用 "合成事件" 作为参数调用。
onChange = (e) => setInput(e.target.value)
TimePicker 和 onChange 处理程序
但是,在 MUI 的 TimePicker
组件的情况下,无论何时调用 onChange
处理程序,提供给处理程序的参数都不是 "合成事件",而是组件的数据值。
Object { "$L": "en", "$u": undefined, "$d": Date Tue Jun 20 2023 10:10:00 GMT+0530 (India Standard Time), "$x": {}, "$y": 2023, "$M": 5, "$D": 20, "$W": 2, "$H": 0, "$m": 10, … }
如您所见,没有 event.target.value
,值只是 event
。
因此,当 Formik 尝试访问 event.target.value
时,它无法成功。因此,该值不会反映在组件中。
解决方案
为了解决这个问题,您需要创建自己的自定义 onChange
事件处理程序。您可以通过使用 Formik 中提供的 setFieldValue 来实现这一点。
这将自动为您设置 mondayFrom
字段的值。
<TimePicker
{...field}
ampm={false}
format="HH:mm"
onChange={(e) => form.setFieldValue(field.name, e)}
slotProps={{
textField: {
label: "Monday From",
size: "small",
fullWidth: true,
},
}}
/>
上面的数据对象 e
还具有一个属性 $d
,您可以使用它来获取字符串格式的日期时间值:
console.log(e["$d"])
// 日期 Tue Jun 20 2023 10:10:00 GMT+0530 (India Standard Time)
希望这可以帮助您!
英文:
Gist
The problem here is, that the component that you are using (TimePicker
), behaves a bit differently than other components.
Formik and onChange handler
Formik, as you may know, makes it easier to develop forms in react. It does this, maintaing internal state of all input components, and by calling onChange
handler whenever user enters input in the input
component.
So normally, when there is a input change, onChange
handles gets called with "synthetic event" as an argument.
onChange = (e) => setInput(e.target.value)
TimePicker and onChange handler
But, in the case of TimePicker
component in MUI, whenever the onChange
handler is called, arguments that is provided to the handler, is not "synthetic event", but the component's data value.
Object { "$L": "en", "$u": undefined, "$d": Date Tue Jun 20 2023 10:10:00 GMT+0530 (India Standard Time), "$x": {}, "$y": 2023, "$M": 5, "$D": 20, "$W": 2, "$H": 0, "$m": 10, … }
As you can see, there is no event.target.value
, the value is just event
.
So, when Formik tries to access event.target.value
, it is not able to. And therefore, the value is not reflected in the component.
The Solution
In order to circumvent this problem, you need to create your own custom onChange
event handler. And you can do this by using, setFieldValue which is present in Formik.
And this will essentially set the mondayFrom
field value automatically for you.
<TimePicker
{...field}
ampm={false}
format="HH:mm"
onChange={(e) => form.setFieldValue(field.name, e)}
slotProps={{
textField: {
label: "Monday From",
size: "small",
fullWidth: true,
},
}}
/>
The data object e
above, also has a property "$d" using which you could get the date time value in string format:
console.log(e["$d"])
// Date Tue Jun 20 2023 10:10:00 GMT+0530 (India Standard Time)
Hope this helps!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论