-
Notifications
You must be signed in to change notification settings - Fork 496
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Controlled Panels #284
Controlled Panels #284
Changes from 5 commits
f51ed13
84dd923
13eb1db
0d2048c
1d4409b
0b43012
bf8c611
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -212,6 +212,18 @@ http://react-component.github.io/calendar/examples/index.html | |
<td></td> | ||
<td>date input's placeholder</td> | ||
</tr> | ||
<tr> | ||
<td>mode</td> | ||
<td>enum('time', 'date', 'month', 'year', 'decade')</td> | ||
<td>'date'</td> | ||
<td>controll which kind of panel should be shown</td> | ||
</tr> | ||
<tr> | ||
<td>onPanelChange</td> | ||
<td>Function(date: moment, mode)</td> | ||
<td></td> | ||
<td>called when panel changed</td> | ||
</tr> | ||
</tbody> | ||
</table> | ||
|
||
|
@@ -348,6 +360,18 @@ http://react-component.github.io/calendar/examples/index.html | |
<td>both</td> | ||
<td>whether fix start or end selected value. check start-end-range example</td> | ||
</tr> | ||
<tr> | ||
<td>mode</td> | ||
<td>enum('date', 'month', 'year', 'decade')[]</td> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. RangeCalendar 还不支持受控展示 timePicker,交互有点冲突。 |
||
<td>['date', 'date']</td> | ||
<td>controll which kind of panels should be shown</td> | ||
</tr> | ||
<tr> | ||
<td>onPanelChange</td> | ||
<td>Function(date: moment[], mode)</td> | ||
<td></td> | ||
<td>called when panels changed</td> | ||
</tr> | ||
</tbody> | ||
</table> | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,27 +50,28 @@ function goDay(direction) { | |
|
||
const Calendar = createReactClass({ | ||
propTypes: { | ||
disabledDate: PropTypes.func, | ||
disabledTime: PropTypes.any, | ||
prefixCls: PropTypes.string, | ||
className: PropTypes.string, | ||
style: PropTypes.object, | ||
defaultValue: PropTypes.object, | ||
value: PropTypes.object, | ||
selectedValue: PropTypes.object, | ||
defaultValue: PropTypes.object, | ||
className: PropTypes.string, | ||
mode: PropTypes.oneOf(['time', 'date', 'month', 'year', 'decade']), | ||
locale: PropTypes.object, | ||
showDateInput: PropTypes.bool, | ||
showWeekNumber: PropTypes.bool, | ||
style: PropTypes.object, | ||
showToday: PropTypes.bool, | ||
showDateInput: PropTypes.bool, | ||
visible: PropTypes.bool, | ||
showOk: PropTypes.bool, | ||
onSelect: PropTypes.func, | ||
onOk: PropTypes.func, | ||
showOk: PropTypes.bool, | ||
prefixCls: PropTypes.string, | ||
onKeyDown: PropTypes.func, | ||
timePicker: PropTypes.element, | ||
dateInputPlaceholder: PropTypes.any, | ||
onClear: PropTypes.func, | ||
onChange: PropTypes.func, | ||
onPanelChange: PropTypes.func, | ||
disabledDate: PropTypes.func, | ||
disabledTime: PropTypes.any, | ||
renderFooter: PropTypes.func, | ||
renderSidebar: PropTypes.func, | ||
}, | ||
|
@@ -83,13 +84,19 @@ const Calendar = createReactClass({ | |
showDateInput: true, | ||
timePicker: null, | ||
onOk: noop, | ||
onPanelChange: noop, | ||
}; | ||
}, | ||
getInitialState() { | ||
return { | ||
showTimePicker: false, | ||
mode: this.props.mode || 'date', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. defaultProps? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
我更新下。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这里还是不能改,mode 这种可是受控属性,不能设置默认值的。 由于受控面板属于高阶用法,也不准备支持 defaultMode |
||
}; | ||
}, | ||
componentWillReceiveProps(nextProps) { | ||
if ('mode' in nextProps) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 判断一下 |
||
this.setState({ mode: nextProps.mode }); | ||
} | ||
}, | ||
onKeyDown(event) { | ||
if (event.target.nodeName.toLowerCase() === 'input') { | ||
return undefined; | ||
|
@@ -189,18 +196,21 @@ const Calendar = createReactClass({ | |
source: 'todayButton', | ||
}); | ||
}, | ||
onPanelChange(mode) { | ||
const { props, state } = this; | ||
if (!('mode' in props)) { | ||
this.setState({ mode }); | ||
} | ||
props.onPanelChange(state.value, mode); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这里其实有个小争议点,文档写的 onPanelChange 是 panel change 的回到。 但比如我刚加的 demo, 在 受控模式下,认为的改变 props.mode 引发的 panel change 是否要触发这个回调呢?目前是没有的 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
这种先忽略,目前我们不少的表单控件都不会因为人工重置 value 而触发 onChange |
||
}, | ||
getRootDOMNode() { | ||
return ReactDOM.findDOMNode(this); | ||
}, | ||
openTimePicker() { | ||
this.setState({ | ||
showTimePicker: true, | ||
}); | ||
this.onPanelChange('time'); | ||
}, | ||
closeTimePicker() { | ||
this.setState({ | ||
showTimePicker: false, | ||
}); | ||
this.onPanelChange('date'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这里可以把默认的 mode 抽离成全局变量 defaultMode = 'date', 可维护性好一点 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这个 +1,不过现在 rc-calendar 里面直接使用字符串的地方太多了,你后边再单独一个 commit 更新这些 code style 吧,顺便熟悉 rc-calendar 的代码。 |
||
}, | ||
render() { | ||
const props = this.props; | ||
|
@@ -210,7 +220,8 @@ const Calendar = createReactClass({ | |
disabledTime, | ||
} = props; | ||
const state = this.state; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 冗余的赋值,直接解构好了 |
||
const { value, selectedValue, showTimePicker } = state; | ||
const { value, selectedValue, mode } = state; | ||
const showTimePicker = mode === 'time'; | ||
const disabledTimeConfig = showTimePicker && disabledTime && timePicker ? | ||
getTimeConfig(selectedValue, disabledTime) : null; | ||
|
||
|
@@ -248,8 +259,10 @@ const Calendar = createReactClass({ | |
<div className={`${prefixCls}-date-panel`}> | ||
<CalendarHeader | ||
locale={locale} | ||
onValueChange={this.setValue} | ||
mode={mode} | ||
value={value} | ||
onValueChange={this.setValue} | ||
onPanelChange={this.onPanelChange} | ||
showTimePicker={showTimePicker} | ||
prefixCls={prefixCls} | ||
/> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,8 +10,7 @@ import TimePickerButton from './calendar/TimePickerButton'; | |
import CommonMixin from './mixin/CommonMixin'; | ||
import { syncTime, getTodayTime, isAllowedDate } from './util/'; | ||
|
||
function noop() { | ||
} | ||
function noop() {} | ||
|
||
function isEmptyArray(arr) { | ||
return Array.isArray(arr) && (arr.length === 0 || arr.every(i => !i)); | ||
|
@@ -62,6 +61,7 @@ const RangeCalendar = createReactClass({ | |
defaultValue: PropTypes.any, | ||
value: PropTypes.any, | ||
hoverValue: PropTypes.any, | ||
mode: PropTypes.arrayOf(PropTypes.oneOf(['date', 'month', 'year', 'decade'])), | ||
timePicker: PropTypes.any, | ||
showOk: PropTypes.bool, | ||
showToday: PropTypes.bool, | ||
|
@@ -74,6 +74,7 @@ const RangeCalendar = createReactClass({ | |
onSelect: PropTypes.func, | ||
onValueChange: PropTypes.func, | ||
onHoverChange: PropTypes.func, | ||
onPanelChange: PropTypes.func, | ||
format: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), | ||
onClear: PropTypes.func, | ||
type: PropTypes.any, | ||
|
@@ -89,6 +90,7 @@ const RangeCalendar = createReactClass({ | |
defaultSelectedValue: [], | ||
onValueChange: noop, | ||
onHoverChange: noop, | ||
onPanelChange: noop, | ||
disabledTime: noop, | ||
showToday: true, | ||
}; | ||
|
@@ -105,8 +107,7 @@ const RangeCalendar = createReactClass({ | |
hoverValue: props.hoverValue || [], | ||
value, | ||
showTimePicker: false, | ||
isStartMonthYearPanelShow: false, | ||
isEndMonthYearPanelShow: false, | ||
mode: props.mode || ['date', 'date'], | ||
}; | ||
}, | ||
|
||
|
@@ -128,6 +129,9 @@ const RangeCalendar = createReactClass({ | |
newState.prevSelectedValue = nextProps.selectedValue; | ||
this.setState(newState); | ||
} | ||
if ('mode' in nextProps) { | ||
this.setState({ mode: nextProps.mode }); | ||
} | ||
}, | ||
|
||
onDatePanelEnter() { | ||
|
@@ -243,12 +247,26 @@ const RangeCalendar = createReactClass({ | |
return this.fireValueChange(value); | ||
}, | ||
|
||
onStartPanelChange({ showMonthPanel, showYearPanel }) { | ||
this.setState({ isStartMonthYearPanelShow: showMonthPanel || showYearPanel }); | ||
onStartPanelChange(mode) { | ||
const { props, state } = this; | ||
const newMode = [mode, state.mode[1]]; | ||
if (!('mode' in props)) { | ||
this.setState({ | ||
mode: newMode, | ||
}); | ||
} | ||
props.onPanelChange(state.value, newMode); | ||
}, | ||
|
||
onEndPanelChange({ showMonthPanel, showYearPanel }) { | ||
this.setState({ isEndMonthYearPanelShow: showMonthPanel || showYearPanel }); | ||
onEndPanelChange(mode) { | ||
const { props, state } = this; | ||
const newMode = [state.mode[0], mode]; | ||
if (!('mode' in props)) { | ||
this.setState({ | ||
mode: newMode, | ||
}); | ||
} | ||
props.onPanelChange(state.value, newMode); | ||
}, | ||
|
||
getStartValue() { | ||
|
@@ -316,6 +334,10 @@ const RangeCalendar = createReactClass({ | |
isAllowedDate(selectedValue[1], this.props.disabledDate, this.disabledEndTime); | ||
}, | ||
|
||
isMonthYearPanelShow(mode) { | ||
return ['month', 'year', 'decade'].includes(mode); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. includes 是 es6 的方法 http://kangax.github.io/compat-table/es2016plus/ 改用 indexOf ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 现在 antd 会要求低版本浏览器引入 polyfill 的。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这里还是建议改一下,毕竟是底层的 rc-components, 小坑埋得越少越好 |
||
}, | ||
|
||
hasSelectedValue() { | ||
const { selectedValue } = this.state; | ||
return !!selectedValue[1] && !!selectedValue[0]; | ||
|
@@ -416,7 +438,6 @@ const RangeCalendar = createReactClass({ | |
render() { | ||
const props = this.props; | ||
const state = this.state; | ||
const { showTimePicker, isStartMonthYearPanelShow, isEndMonthYearPanelShow } = state; | ||
const { | ||
prefixCls, dateInputPlaceholder, | ||
timePicker, showOk, locale, showClear, | ||
|
@@ -425,6 +446,8 @@ const RangeCalendar = createReactClass({ | |
const { | ||
hoverValue, | ||
selectedValue, | ||
mode, | ||
showTimePicker, | ||
} = state; | ||
const className = { | ||
[props.className]: !!props.className, | ||
|
@@ -501,14 +524,15 @@ const RangeCalendar = createReactClass({ | |
disabledMonth={this.disabledStartMonth} | ||
format={this.getFormat()} | ||
value={startValue} | ||
mode={mode[0]} | ||
placeholder={placeholder1} | ||
onInputSelect={this.onStartInputSelect} | ||
onValueChange={this.onStartValueChange} | ||
onPanelChange={this.onStartPanelChange} | ||
timePicker={timePicker} | ||
showTimePicker={showTimePicker} | ||
enablePrev | ||
enableNext={!isClosestMonths || isEndMonthYearPanelShow} | ||
enableNext={!isClosestMonths || this.isMonthYearPanelShow(mode[1])} | ||
/> | ||
<span className={`${prefixCls}-range-middle`}>~</span> | ||
<CalendarPart | ||
|
@@ -520,14 +544,15 @@ const RangeCalendar = createReactClass({ | |
timePickerDisabledTime={this.getEndDisableTime()} | ||
placeholder={placeholder2} | ||
value={endValue} | ||
mode={mode[1]} | ||
onInputSelect={this.onEndInputSelect} | ||
onValueChange={this.onEndValueChange} | ||
onPanelChange={this.onEndPanelChange} | ||
timePicker={timePicker} | ||
showTimePicker={showTimePicker} | ||
disabledTime={this.disabledEndTime} | ||
disabledMonth={this.disabledEndMonth} | ||
enablePrev={!isClosestMonths || isStartMonthYearPanelShow} | ||
enablePrev={!isClosestMonths || this.isMonthYearPanelShow(mode[0])} | ||
enableNext | ||
/> | ||
</div> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
新增 API mode & onPanelChange 用于控制当前展示的面板。