我有这个简单的 v6 redux-form 输入,它呈现一个自定义组件,该组件使用 react-day-picker 填充其值。
https://github.com/gpbl/react-day-picker
我选择 react-day-picker 而不是其他的,因为它不依赖于 moment.js 并且适用于我当前的设置。
当我关注该字段时,我希望弹出日期选择器,但是如果我单击不是日期选择器的任何位置,我希望它消失。
本质上,我希望我的 React datepicker 像 jQueryUI 一样工作:
https://jqueryui.com/datepicker/
我最终得出的三种情况是:
我单击该字段,日期选择器弹出,但不会消失,除非我选择一个日期或再次单击该字段(这对我们的需要来说太死板了)。
我单击该字段,日期选择器会弹出,但如果我单击任何位置,它会很快消失,因为输入字段的 onBlur 在处理日期选择器的单击事件以使用所选日期填充该字段之前被调用。
我单击该字段,日期选择器弹出,自动聚焦,正确模糊,除非我单击任何不是 <body> 或日期选择器的东西。
我首先尝试使用一个包含整个页面的同级空 div,所以当我单击空 div 时,它会正确切换日期选择器。这适用于 z-indexes 和 position: 固定,直到我更改了 datepicker 的月份,这似乎重新渲染了 datepicker 并弄乱了点击的顺序,这再次导致了情况 2)。
我最近的尝试是在日期选择器 div 弹出时自动聚焦它,所以当我模糊任何不是日期选择器的东西时,它会切换日期选择器。这在理论上是可行的,除了 datepicker 是一个内部有许多嵌套 <div> 的组件来控制日、周、月、禁用日......所以当我点击“日”时,它会注册一个模糊,因为我m 点击 'day' ,而不是最初关注<div>
的根 'datepicker' 。<div>
上面的解决方案是调整 'datepicker'<div>
的 onBlur 以便它只会在 document.activeElement 为 <body> 时切换 datepicker,但这只有在我不单击另一个表单字段时才有效。
WizardFormPageOne.js:
function WizardFormPageOne({ handleSubmit }) {
return (
<form onSubmit={handleSubmit} className="col-xs-6">
<h1>WizardFormPageOne</h1>
<div className="card">
<div className="card-block">
<div className="form-group">
<label htmlFor="first">Label 1</label>
<Field type="text" name="first" component={DateInput} className="form-control" />
</div>
...
export default reduxForm({
form: 'wizardForm',
destroyOnUnmount: false,
})(WizardFormPageOne);
日期输入.js:
import React from 'react';
import styles from './styles.css';
import DatePicker from '../DatePicker';
class DateInput extends React.Component { // eslint-disable-line react/prefer-stateless-function
constructor(props) {
super(props);
this.state = {
dateValue: new Date(),
activeDateWidget: false,
};
}
changeDate = (date) => {
this.setState({
dateValue: date,
});
}
changeActiveDateWidget = (e) => {
e.stopPropagation();
this.setState({
activeDateWidget: !this.state.activeDateWidget,
});
}
render() {
const { input, meta } = this.props;
const { dateValue, activeDateWidget } = this.state;
return (
<div className={styles.dateInput}>
<input
{...input}
className="form-control"
type="text"
value={dateValue}
onClick={this.changeActiveDateWidget}
// onBlur={this.changeActiveDateWidget}
/>
{activeDateWidget ? (
<div>
<DatePicker
changeActiveDateWidget={this.changeActiveDateWidget}
changeDate={this.changeDate}
dateValue={dateValue}
/>
</div>
) : (
<div></div>
)}
</div>
);
}
}
export default DateInput;
日期选择器.js:
import React from 'react';
import 'react-day-picker/lib/style.css';
import DayPicker, { DateUtils } from 'react-day-picker';
import styles from './styles.css';
import disabledDays from './disabledDays';
class DatePicker extends React.Component { // eslint-disable-line react/prefer-stateless-function
constructor(props) {
super(props);
this.state = {
selectedDay: new Date(),
};
}
componentDidMount() {
if (this._input) {
this._input.focus();
}
}
handleDayClick = (e, day, { disabled }) => {
e.stopPropagation();
if (disabled) {
return;
}
this.setState({ selectedDay: day }, () => {
this.props.changeDate(day);
this.props.changeActiveDateWidget();
});
}
focusThisComponent = (e) => {
if (e) {
this._input = e;
}
}
focusIt = () => {
console.log('focusing');
}
blurIt = () => {
console.log('blurring');
setTimeout(() => {
if (document.activeElement == document.body) {
this.props.changeActiveDateWidget();
}
}, 1);
}
render() {
const { changeActiveDateWidget } = this.props;
const { selectedDay } = this.state;
return (
<div
className={styles.datePicker}
ref={this.focusThisComponent}
tabIndex="1"
onFocus={this.focusIt}
onBlur={this.blurIt}
>
<DayPicker
id="THISTHING"
initialMonth={selectedDay}
disabledDays={disabledDays}
selectedDays={(day) => DateUtils.isSameDay(selectedDay, day)}
onDayClick={this.handleDayClick}
/>
</div>
);
}
}
export default DatePicker;
这是我现在遇到的问题的截屏视频:
http://screencast.com/t/kZuIwUzl
日期选择器会正确切换,除非单击另一个字段,此时它会停止正确模糊/切换。我所有的修修补补要么导致我进入上面列出的三个场景之一。