提交 fd1d54cf 编写于 作者: A afc163

Merge pull request #1298 from ant-design/refactor-datepicker-hoc

refactor: remove mixin
import React from 'react';
import defaultLocale from './locale/zh_CN';
import DateTimeFormat from 'gregorian-calendar-format';
import GregorianCalendar from 'gregorian-calendar';
export default {
contextTypes: {
antLocale: React.PropTypes.object,
},
getLocale() {
let locale = defaultLocale;
if (this.context.antLocale && this.context.antLocale.DatePicker) {
locale = this.context.antLocale.DatePicker;
}
// 统一合并为完整的 Locale
const result = { ...locale, ...this.props.locale };
result.lang = { ...locale.lang, ...this.props.locale.lang };
return result;
},
getFormatter() {
if (!this.formats) {
this.formats = {};
}
const formats = this.formats;
const format = this.props.format;
if (formats[format]) {
return formats[format];
}
formats[format] = new DateTimeFormat(format, this.getLocale().lang.format);
return formats[format];
},
parseDateFromValue(value) {
if (value) {
if (typeof value === 'string') {
return this.getFormatter().parse(value, { locale: this.getLocale() });
} else if (value instanceof Date) {
let date = new GregorianCalendar(this.getLocale());
date.setTime(+value);
return date;
}
}
return value;
},
// remove input readonly warning
handleInputChange() {
},
toggleOpen(e) {
this.setState({
open: e.open
});
},
};
...@@ -2,83 +2,61 @@ import React from 'react'; ...@@ -2,83 +2,61 @@ import React from 'react';
import GregorianCalendar from 'gregorian-calendar'; import GregorianCalendar from 'gregorian-calendar';
import RangeCalendar from 'rc-calendar/lib/RangeCalendar'; import RangeCalendar from 'rc-calendar/lib/RangeCalendar';
import DatePicker from 'rc-calendar/lib/Picker'; import DatePicker from 'rc-calendar/lib/Picker';
import TimePicker from 'rc-time-picker';
import classNames from 'classnames'; import classNames from 'classnames';
import PickerMixin from './PickerMixin';
export default React.createClass({ export default React.createClass({
getDefaultProps() { getDefaultProps() {
return { return {
defaultValue: [], defaultValue: [],
format: 'yyyy-MM-dd',
startPlaceholder: '开始日期', startPlaceholder: '开始日期',
endPlaceholder: '结束日期', endPlaceholder: '结束日期',
transitionName: 'slide-up',
popupStyle: {},
onChange() {
},
onOk() {
},
locale: {},
align: {
offset: [0, -9],
},
open: false
}; };
}, },
getInitialState() { getInitialState() {
const { value, defaultValue } = this.props; const { value, defaultValue, parseDateFromValue } = this.props;
const start = (value && value[0]) || defaultValue[0]; const start = (value && value[0]) || defaultValue[0];
const end = (value && value[1]) || defaultValue[1]; const end = (value && value[1]) || defaultValue[1];
return { return {
value: [ value: [
this.parseDateFromValue(start), parseDateFromValue(start),
this.parseDateFromValue(end) parseDateFromValue(end)
] ]
}; };
}, },
mixins: [PickerMixin],
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
if ('value' in nextProps) { if ('value' in nextProps) {
const value = nextProps.value || []; const value = nextProps.value || [];
const start = this.parseDateFromValue(value[0]); const start = nextProps.parseDateFromValue(value[0]);
const end = this.parseDateFromValue(value[1]); const end = nextProps.parseDateFromValue(value[1]);
this.setState({ this.setState({
value: [start, end] value: [start, end]
}); });
} }
}, },
handleChange(value) { handleChange(value) {
if (!('value' in this.props)) { const props = this.props;
if (!('value' in props)) {
this.setState({ value }); this.setState({ value });
} }
const startDate = value[0] ? new Date(value[0].getTime()) : null; const startDate = value[0] ? new Date(value[0].getTime()) : null;
const endDate = value[1] ? new Date(value[1].getTime()) : null; const endDate = value[1] ? new Date(value[1].getTime()) : null;
const startDateString = value[0] ? this.getFormatter().format(value[0]) : ''; const startDateString = value[0] ? props.getFormatter().format(value[0]) : '';
const endDateString = value[1] ? this.getFormatter().format(value[1]) : ''; const endDateString = value[1] ? props.getFormatter().format(value[1]) : '';
this.props.onChange([startDate, endDate], [startDateString, endDateString]); props.props.onChange([startDate, endDate], [startDateString, endDateString]);
}, },
render() { render() {
const locale = this.getLocale(); const props = this.props;
const locale = props.locale;
// 以下两行代码 // 以下两行代码
// 给没有初始值的日期选择框提供本地化信息 // 给没有初始值的日期选择框提供本地化信息
// 否则会以周日开始排 // 否则会以周日开始排
let defaultCalendarValue = new GregorianCalendar(locale); let defaultCalendarValue = new GregorianCalendar(locale);
defaultCalendarValue.setTime(Date.now()); defaultCalendarValue.setTime(Date.now());
const { disabledDate, showTime, size, startPlaceholder, endPlaceholder, getCalendarContainer, const { disabledDate, showTime, startPlaceholder, endPlaceholder, getCalendarContainer,
transitionName, disabled, popupStyle, align, style, onOk } = this.props; transitionName, disabled, popupStyle, align, style, onOk } = this.props;
const state = this.state; const state = this.state;
let timePicker = null;
if (showTime) {
timePicker = (<TimePicker
prefixCls="ant-time-picker"
placeholder={locale.lang.timePlaceholder}
transitionName="slide-up" />);
}
const calendarClassName = classNames({ const calendarClassName = classNames({
['ant-calendar-time']: showTime, ['ant-calendar-time']: showTime,
}); });
...@@ -91,7 +69,7 @@ export default React.createClass({ ...@@ -91,7 +69,7 @@ export default React.createClass({
onOk: this.handleChange, onOk: this.handleChange,
}; };
if (timePicker) { if (props.timePicker) {
pickerChangeHandler.onChange = (value) => { pickerChangeHandler.onChange = (value) => {
// Click clear button // Click clear button
if (value === null || value.length === 0) { if (value === null || value.length === 0) {
...@@ -106,7 +84,7 @@ export default React.createClass({ ...@@ -106,7 +84,7 @@ export default React.createClass({
<RangeCalendar <RangeCalendar
prefixCls="ant-calendar" prefixCls="ant-calendar"
className={calendarClassName} className={calendarClassName}
timePicker={timePicker} timePicker={props.timePicker}
disabledDate={disabledDate} disabledDate={disabledDate}
dateInputPlaceholder={[startPlaceholder, endPlaceholder]} dateInputPlaceholder={[startPlaceholder, endPlaceholder]}
locale={locale.lang} locale={locale.lang}
...@@ -116,19 +94,7 @@ export default React.createClass({ ...@@ -116,19 +94,7 @@ export default React.createClass({
/> />
); );
const pickerClass = classNames({ return (<span className={props.pickerClass} style={style}>
'ant-calendar-picker': true,
'ant-calendar-picker-open': state.open
});
const pickerInputClass = classNames({
'ant-calendar-range-picker': true,
'ant-input': true,
'ant-input-lg': size === 'large',
'ant-input-sm': size === 'small',
});
return (<span className={pickerClass} style={style}>
<DatePicker <DatePicker
transitionName={transitionName} transitionName={transitionName}
disabled={disabled} disabled={disabled}
...@@ -138,8 +104,8 @@ export default React.createClass({ ...@@ -138,8 +104,8 @@ export default React.createClass({
style={popupStyle} style={popupStyle}
align={align} align={align}
getCalendarContainer={getCalendarContainer} getCalendarContainer={getCalendarContainer}
onOpen={this.toggleOpen} onOpen={props.toggleOpen}
onClose={this.toggleOpen} onClose={props.toggleOpen}
{...pickerChangeHandler} {...pickerChangeHandler}
> >
{ {
...@@ -147,18 +113,18 @@ export default React.createClass({ ...@@ -147,18 +113,18 @@ export default React.createClass({
const start = value[0]; const start = value[0];
const end = value[1]; const end = value[1];
return ( return (
<span className={pickerInputClass} disabled={disabled}> <span className={props.pickerInputClass} disabled={disabled}>
<input <input
disabled={disabled} disabled={disabled}
onChange={this.handleInputChange} onChange={props.handleInputChange}
value={start && this.getFormatter().format(start)} value={start && props.getFormatter().format(start)}
placeholder={startPlaceholder} placeholder={startPlaceholder}
className="ant-calendar-range-picker-input" /> className="ant-calendar-range-picker-input" />
<span className="ant-calendar-range-picker-separator"> ~ </span> <span className="ant-calendar-range-picker-separator"> ~ </span>
<input <input
disabled={disabled} disabled={disabled}
onChange={this.handleInputChange} onChange={props.handleInputChange}
value={end && this.getFormatter().format(end)} value={end && props.getFormatter().format(end)}
placeholder={endPlaceholder} placeholder={endPlaceholder}
className="ant-calendar-range-picker-input" /> className="ant-calendar-range-picker-input" />
<span className="ant-calendar-picker-icon" /> <span className="ant-calendar-picker-icon" />
......
...@@ -2,51 +2,33 @@ import React from 'react'; ...@@ -2,51 +2,33 @@ import React from 'react';
import MonthCalendar from 'rc-calendar/lib/MonthCalendar'; import MonthCalendar from 'rc-calendar/lib/MonthCalendar';
import RcDatePicker from 'rc-calendar/lib/Picker'; import RcDatePicker from 'rc-calendar/lib/Picker';
import GregorianCalendar from 'gregorian-calendar'; import GregorianCalendar from 'gregorian-calendar';
import TimePicker from 'rc-time-picker';
import classNames from 'classnames'; import classNames from 'classnames';
import PickerMixin from './PickerMixin';
export default function createPicker(TheCalendar, defaultFormat) { export default function createPicker(TheCalendar) {
return React.createClass({ return React.createClass({
getDefaultProps() {
return {
format: defaultFormat || 'yyyy-MM-dd',
transitionName: 'slide-up',
popupStyle: {},
onChange() {
},
onOk() {
},
locale: {},
align: {
offset: [0, -9],
},
open: false,
};
},
getInitialState() { getInitialState() {
return { return {
value: this.parseDateFromValue(this.props.value || this.props.defaultValue) value: this.props.parseDateFromValue(this.props.value || this.props.defaultValue)
}; };
}, },
mixins: [PickerMixin],
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
if ('value' in nextProps) { if ('value' in nextProps) {
this.setState({ this.setState({
value: this.parseDateFromValue(nextProps.value) value: nextProps.parseDateFromValue(nextProps.value)
}); });
} }
}, },
handleChange(value) { handleChange(value) {
if (!('value' in this.props)) { const props = this.props;
if (!('value' in props)) {
this.setState({ value }); this.setState({ value });
} }
const timeValue = value ? new Date(value.getTime()) : null; const timeValue = value ? new Date(value.getTime()) : null;
this.props.onChange(timeValue, value ? this.getFormatter().format(value) : ''); props.onChange(timeValue, value ? props.getFormatter().format(value) : '');
}, },
render() { render() {
const props = this.props; const props = this.props;
const locale = this.getLocale(); const locale = props.locale;
// 以下两行代码 // 以下两行代码
// 给没有初始值的日期选择框提供本地化信息 // 给没有初始值的日期选择框提供本地化信息
// 否则会以周日开始排 // 否则会以周日开始排
...@@ -56,12 +38,6 @@ export default function createPicker(TheCalendar, defaultFormat) { ...@@ -56,12 +38,6 @@ export default function createPicker(TheCalendar, defaultFormat) {
const placeholder = ('placeholder' in props) const placeholder = ('placeholder' in props)
? props.placeholder : locale.lang.placeholder; ? props.placeholder : locale.lang.placeholder;
const timePicker = props.showTime ? (<TimePicker
prefixCls="ant-time-picker"
placeholder={locale.lang.timePlaceholder}
transitionName="slide-up" />)
: null;
const disabledTime = props.showTime ? props.disabledTime : null; const disabledTime = props.showTime ? props.disabledTime : null;
const calendarClassName = classNames({ const calendarClassName = classNames({
...@@ -93,7 +69,7 @@ export default function createPicker(TheCalendar, defaultFormat) { ...@@ -93,7 +69,7 @@ export default function createPicker(TheCalendar, defaultFormat) {
disabledDate={props.disabledDate} disabledDate={props.disabledDate}
disabledTime={disabledTime} disabledTime={disabledTime}
locale={locale.lang} locale={locale.lang}
timePicker={timePicker} timePicker={props.timePicker}
defaultValue={defaultCalendarValue} defaultValue={defaultCalendarValue}
dateInputPlaceholder={placeholder} dateInputPlaceholder={placeholder}
prefixCls="ant-calendar" prefixCls="ant-calendar"
...@@ -101,18 +77,6 @@ export default function createPicker(TheCalendar, defaultFormat) { ...@@ -101,18 +77,6 @@ export default function createPicker(TheCalendar, defaultFormat) {
{...calendarHandler} /> {...calendarHandler} />
); );
const pickerClass = classNames({
'ant-calendar-picker': true,
'ant-calendar-picker-open': this.state.open,
});
const inputClass = classNames({
'ant-calendar-picker-input': true,
'ant-input': true,
'ant-input-lg': props.size === 'large',
'ant-input-sm': props.size === 'small',
});
// default width for showTime // default width for showTime
const pickerStyle = {}; const pickerStyle = {};
if (props.showTime) { if (props.showTime) {
...@@ -120,7 +84,7 @@ export default function createPicker(TheCalendar, defaultFormat) { ...@@ -120,7 +84,7 @@ export default function createPicker(TheCalendar, defaultFormat) {
} }
return ( return (
<span className={pickerClass} style={{ ...pickerStyle, ...props.style }}> <span className={props.pickerClass} style={{ ...pickerStyle, ...props.style }}>
<RcDatePicker <RcDatePicker
transitionName={props.transitionName} transitionName={props.transitionName}
disabled={props.disabled} disabled={props.disabled}
...@@ -130,8 +94,8 @@ export default function createPicker(TheCalendar, defaultFormat) { ...@@ -130,8 +94,8 @@ export default function createPicker(TheCalendar, defaultFormat) {
style={props.popupStyle} style={props.popupStyle}
align={props.align} align={props.align}
getCalendarContainer={props.getCalendarContainer} getCalendarContainer={props.getCalendarContainer}
onOpen={this.toggleOpen} onOpen={props.toggleOpen}
onClose={this.toggleOpen} onClose={props.toggleOpen}
{...pickerChangeHandler} {...pickerChangeHandler}
> >
{ {
...@@ -140,10 +104,10 @@ export default function createPicker(TheCalendar, defaultFormat) { ...@@ -140,10 +104,10 @@ export default function createPicker(TheCalendar, defaultFormat) {
<span> <span>
<input <input
disabled={props.disabled} disabled={props.disabled}
onChange={this.handleInputChange} onChange={props.handleInputChange}
value={value && this.getFormatter().format(value)} value={value && props.getFormatter().format(value)}
placeholder={placeholder} placeholder={placeholder}
className={inputClass} /> className={props.pickerInputClass} />
<span className="ant-calendar-picker-icon" /> <span className="ant-calendar-picker-icon" />
</span> </span>
); );
......
import RcCalendar from 'rc-calendar'; import RcCalendar from 'rc-calendar';
import MonthCalendar from 'rc-calendar/lib/MonthCalendar'; import MonthCalendar from 'rc-calendar/lib/MonthCalendar';
import createPicker from './createPicker'; import createPicker from './createPicker';
import wrapPicker from './wrapPicker';
import RangePicker from './RangePicker'; import RangePicker from './RangePicker';
import Calendar from './Calendar'; import Calendar from './Calendar';
const DatePicker = createPicker(RcCalendar); const DatePicker = wrapPicker(createPicker(RcCalendar));
const MonthPicker = createPicker(MonthCalendar, 'yyyy-MM'); const MonthPicker = wrapPicker(createPicker(MonthCalendar), 'yyyy-MM');
DatePicker.Calendar = Calendar; DatePicker.Calendar = Calendar;
DatePicker.RangePicker = RangePicker; DatePicker.RangePicker = wrapPicker(RangePicker, 'yyyy-MM-dd');
DatePicker.MonthPicker = MonthPicker; DatePicker.MonthPicker = MonthPicker;
export default DatePicker; export default DatePicker;
import React, { PropTypes } from 'react';
import TimePicker from 'rc-time-picker';
import DateTimeFormat from 'gregorian-calendar-format';
import GregorianCalendar from 'gregorian-calendar';
import classNames from 'classnames';
import defaultLocale from './locale/zh_CN';
export default function wrapPicker(Picker, defaultFormat) {
return class PickerWrapper extends React.Component {
static defaultProps = {
format: defaultFormat || 'yyyy-MM-dd',
transitionName: 'slide-up',
popupStyle: {},
onChange() {},
onOk() {},
locale: {},
align: {
offset: [0, -9],
},
open: false
}
static contextTypes = {
antLocale: PropTypes.object,
}
constructor(props) {
super(props);
this.state = {};
}
// remove input readonly warning
handleInputChange() {}
getLocale() {
const props = this.props;
let locale = defaultLocale;
const context = this.context;
if (context.antLocale && context.antLocale.DatePicker) {
locale = context.antLocale.DatePicker;
}
// 统一合并为完整的 Locale
const result = { ...locale, ...props.locale };
result.lang = { ...locale.lang, ...props.locale.lang };
return result;
}
getFormatter = () => {
if (!this.formats) {
this.formats = {};
}
const formats = this.formats;
const format = this.props.format;
if (formats[format]) {
return formats[format];
}
formats[format] = new DateTimeFormat(format, this.getLocale().lang.format);
return formats[format];
}
parseDateFromValue = (value) => {
if (value) {
if (typeof value === 'string') {
return this.getFormatter().parse(value, { locale: this.getLocale() });
} else if (value instanceof Date) {
let date = new GregorianCalendar(this.getLocale());
date.setTime(+value);
return date;
}
}
return value;
}
toggleOpen = (e) => {
this.setState({
open: e.open
});
}
render() {
const props = this.props;
const state = this.state;
const pickerClass = classNames({
'ant-calendar-picker': true,
'ant-calendar-picker-open': state.open
});
const pickerInputClass = classNames({
'ant-calendar-range-picker': true,
'ant-input': true,
'ant-input-lg': props.size === 'large',
'ant-input-sm': props.size === 'small',
});
const locale = this.getLocale();
const timePicker = props.showTime ? (
<TimePicker
prefixCls="ant-time-picker"
placeholder={locale.lang.timePlaceholder}
transitionName="slide-up" />
) : null;
return (
<Picker
{...this.props}
pickerClass={pickerClass}
pickerInputClass={pickerInputClass}
locale={locale}
timePicker={timePicker}
toggleOpen={this.toggleOpen}
handleInputChange={this.handleInputChange}
getFormatter={this.getFormatter}
parseDateFromValue={this.parseDateFromValue}
/>
);
}
};
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册