MuiPickersUtilsProvider切换为datetime-local日期选择器失效求助
原生datetime-local日期选择器替换MUI组件后异常问题
原可正常运行的MUI日期选择器代码
<MuiPickersUtilsProvider utils={MomentUtils}> <KeyboardDateTimePicker className="form-control" value={toDate} onChange={(e) => { setToDate(e); setStopDate(e); }} name="toDate" format={ type === "Yearly" ? "DD MMM hh:mm a" : type === "Monthly" ? "Do hh:mm a" : type === "Weekly" ? "dddd hh:mm a" : type === "Daily" ? "hh:mm a" : SAASDateTimeFormat } minDate={fromDate} /> {invalidMessage ? ( <div className="fv-plugins-message-container"> <div className="fv-help-block">{invalidMessage}</div> </div> ) : null} </MuiPickersUtilsProvider>
原效果:
替换为原生datetime-local后的问题代码
<Form.Control className="form-control" type="datetime-local" name="toDate" minDate={fromDate} value={toDate} onChange={(e) => { setToDate(e); setStopDate(e); }} format={ type === "Yearly" ? "DD MMM hh:mm a" : type === "Monthly" ? "Do hh:mm a" : type === "Weekly" ? "dddd hh:mm a" : type === "Daily" ? "hh:mm a" : SAASDateTimeFormat } {invalidMessage ? ( <div className="fv-plugins-message-container"> <div className="fv-help-block">{invalidMessage}</div> </div> ) : null} />
当前问题:datetime-local选择器无法选择输入框中显示的日期时间,期望显示格式为Sunday 02:40 PM,当前效果:
相关变量值
- toDate:
Sun Jul 31 2022 14:29:59 GMT+0800 (Malaysia Time) - fromDate:
Sun Jul 31 2022 14:40:34 GMT+0800 (Malaysia Time) - SAASDateTimeFormat:
const SAASDateTimeFormat = "DD MMM yyyy hh:mm A"
问题原因及解决方法
1. 核心格式不兼容
原生datetime-local输入框对value有严格格式要求,必须是ISO 8601格式(YYYY-MM-DDTHH:mm),直接传入原生Date对象或moment对象会导致输入框无法解析值,进而无法选择时间。
2. 原生组件不支持自定义format属性
原生HTML的datetime-local不支持format属性,显示格式由浏览器默认控制,无法直接设置为Sunday 02:40 PM这类自定义格式。如需自定义显示,可采用「隐藏原生选择器+显示格式化文本」的方案。
3. 属性名错误
原生组件没有minDate属性,对应限制最小时间的属性是min,需将其转换为符合格式要求的字符串。
4. onChange事件参数错误
原生输入框的onChange返回的是事件对象,需通过e.target.value获取选中值,再转换为Date对象存储。
修正后的代码示例
方案一:保留自定义显示格式
import moment from 'moment'; // 组件内部处理格式化显示文本 const formattedDisplayDate = moment(toDate).format( type === "Yearly" ? "DD MMM hh:mm a" : type === "Monthly" ? "Do hh:mm a" : type === "Weekly" ? "dddd hh:mm a" : type === "Daily" ? "hh:mm a" : SAASDateTimeFormat ); return ( <div> {/* 隐藏的原生datetime-local选择器 */} <input type="datetime-local" name="toDate" className="d-none" min={moment(fromDate).format("YYYY-MM-DDTHH:mm")} value={moment(toDate).format("YYYY-MM-DDTHH:mm")} onChange={(e) => { const newDate = new Date(e.target.value); setToDate(newDate); setStopDate(newDate); }} /> {/* 显示格式化文本的输入框,点击触发原生选择器 */} <input type="text" className="form-control" value={formattedDisplayDate} onClick={() => document.querySelector('[name="toDate"]').showPicker()} readOnly /> {invalidMessage ? ( <div className="fv-plugins-message-container"> <div className="fv-help-block">{invalidMessage}</div> </div> ) : null} </div> );
方案二:接受浏览器默认显示格式(简化版)
<Form.Control className="form-control" type="datetime-local" name="toDate" min={new Date(fromDate).toISOString().slice(0, 16)} value={new Date(toDate).toISOString().slice(0, 16)} onChange={(e) => { const newDate = new Date(e.target.value); setToDate(newDate); setStopDate(newDate); }} /> {invalidMessage ? ( <div className="fv-plugins-message-container"> <div className="fv-help-block">{invalidMessage}</div> </div> ) : null}
内容的提问来源于stack exchange,提问作者Fatt Sky
相关产品推荐
相关产品推荐

