diff --git a/components/date-picker/RangePicker.jsx b/components/date-picker/RangePicker.jsx
index f65d572f6..e62240197 100644
--- a/components/date-picker/RangePicker.jsx
+++ b/components/date-picker/RangePicker.jsx
@@ -8,8 +8,9 @@ import Icon from '../icon'
import Tag from '../tag'
import interopDefault from '../_util/interopDefault'
import { RangePickerProps } from './interface'
-import { hasProp, getOptionProps, initDefaultProps, mergeProps } from '../_util/props-util'
+import { hasProp, getOptionProps, initDefaultProps, mergeProps, getComponentFromProp, isValidElement } from '../_util/props-util'
import BaseMixin from '../_util/BaseMixin'
+import { cloneElement } from '../_util/vnode'
function noop () {}
function getShowDateFromValue (value) {
const [start, end] = value
@@ -130,6 +131,7 @@ export default {
formatValue(value[0], this.format),
formatValue(value[1], this.format),
])
+ this.focus()
},
handleOpenChange (open) {
@@ -174,6 +176,7 @@ export default {
this.setValue(value, true)
this.$emit('ok', value)
+ this.$emit('openChange', false)
},
setValue (value, hidePanel) {
@@ -224,17 +227,18 @@ export default {
)
})
- const rangeNode = (
+ const rangeNode = (operations && operations.length > 0) ? (
- )
+ ) : null
return [rangeNode, customFooter]
},
},
render () {
const props = getOptionProps(this)
+ let suffixIcon = getComponentFromProp(this, 'suffixIcon')
+ suffixIcon = Array.isArray(suffixIcon) ? suffixIcon[0] : suffixIcon
const { sValue: value, sShowDate: showDate, sHoverValue: hoverValue, sOpen: open, $listeners, $scopedSlots } = this
const { calendarChange = noop, ok = noop, focus = noop, blur = noop, panelChange = noop } = $listeners
const {
@@ -296,7 +300,7 @@ export default {
ok: ok,
valueChange: this.handleShowDateChange,
hoverChange: this.handleHoverChange,
- panelChange: panelChange,
+ panelChange,
inputSelect: this.handleCalendarInputSelect,
},
class: calendarClassName,
@@ -316,12 +320,24 @@ export default {
const clearIcon = (!props.disabled && props.allowClear && value && (value[0] || value[1])) ? (
) : null
+ const inputIcon = suffixIcon && (
+ isValidElement(suffixIcon)
+ ? cloneElement(
+ suffixIcon,
+ {
+ class: `${prefixCls}-picker-icon`,
+ },
+ ) : {suffixIcon}) || (
+
+ )
+
const input = ({ value: inputValue }) => {
const start = inputValue[0]
const end = inputValue[1]
@@ -345,7 +361,7 @@ export default {
tabIndex={-1}
/>
{clearIcon}
-
+ {inputIcon}
)
}
diff --git a/components/date-picker/WeekPicker.jsx b/components/date-picker/WeekPicker.jsx
index bd3fa6bf6..d7526e6bf 100644
--- a/components/date-picker/WeekPicker.jsx
+++ b/components/date-picker/WeekPicker.jsx
@@ -3,10 +3,11 @@ import * as moment from 'moment'
import Calendar from '../vc-calendar'
import VcDatePicker from '../vc-calendar/src/Picker'
import Icon from '../icon'
-import { hasProp, getOptionProps, initDefaultProps } from '../_util/props-util'
+import { hasProp, getOptionProps, initDefaultProps, getComponentFromProp, isValidElement } from '../_util/props-util'
import BaseMixin from '../_util/BaseMixin'
import { WeekPickerProps } from './interface'
import interopDefault from '../_util/interopDefault'
+import { cloneElement } from '../_util/vnode'
function formatValue (value, format) {
return (value && value.format(format)) || ''
@@ -74,6 +75,7 @@ export default {
this.setState({ sValue: value })
}
this.$emit('change', value, formatValue(value, this.format))
+ this.focus()
},
clearSelection (e) {
e.preventDefault()
@@ -92,6 +94,8 @@ export default {
render () {
const props = getOptionProps(this)
+ let suffixIcon = getComponentFromProp(this, 'suffixIcon')
+ suffixIcon = Array.isArray(suffixIcon) ? suffixIcon[0] : suffixIcon
const {
prefixCls, disabled, pickerClass, popupStyle,
pickerInputClass, format, allowClear, locale, localeCode, disabledDate,
@@ -119,11 +123,24 @@ export default {
)
const clearIcon = (!disabled && allowClear && this.sValue) ? (
) : null
+
+ const inputIcon = suffixIcon && (
+ isValidElement(suffixIcon)
+ ? cloneElement(
+ suffixIcon,
+ {
+ class: `${prefixCls}-picker-icon`,
+ },
+ ) : {suffixIcon}) || (
+
+ )
+
const input = ({ value }) => {
return (
@@ -138,7 +155,7 @@ export default {
onBlur={blur}
/>
{clearIcon}
-
+ {inputIcon}
)
}
diff --git a/components/date-picker/__tests__/MonthPicker.test.js b/components/date-picker/__tests__/MonthPicker.test.js
index 2e115e9af..f0cf2e6c5 100644
--- a/components/date-picker/__tests__/MonthPicker.test.js
+++ b/components/date-picker/__tests__/MonthPicker.test.js
@@ -1,8 +1,26 @@
+import { mount } from '@vue/test-utils'
+import { asyncExpect } from '@/tests/utils'
+import moment from 'moment'
import DatePicker from '..'
import focusTest from '../../../tests/shared/focusTest'
+import { openPanel, $$ } from './utils'
const { MonthPicker } = DatePicker
describe('MonthPicker', () => {
focusTest(MonthPicker)
+ it('reset select item when popup close', async () => {
+ const wrapper = mount(MonthPicker, {
+ propsData: { value: moment('2018-07-01') },
+ sync: false,
+ attachToDocument: true,
+ })
+ await asyncExpect(() => {
+ openPanel(wrapper)
+ })
+ await asyncExpect(() => {
+ $$('.ant-calendar-month-panel-month')[0].click()
+ $$('.ant-calendar-month-panel-cell')[6].getAttribute('class').split(' ').includes('ant-calendar-month-panel-selected-cell')
+ }, 0)
+ })
})
diff --git a/components/date-picker/__tests__/RangePicker.test.js b/components/date-picker/__tests__/RangePicker.test.js
index 84abd5dde..6d0854b21 100644
--- a/components/date-picker/__tests__/RangePicker.test.js
+++ b/components/date-picker/__tests__/RangePicker.test.js
@@ -325,4 +325,26 @@ describe('RangePicker', () => {
}).not.toThrow()
})
})
+ // https://github.com/ant-design/ant-design/issues/11631
+ it('triggers onOpenChange when click on preset range', async () => {
+ const handleOpenChange = jest.fn()
+ const range = [moment().subtract(2, 'd'), moment()]
+ const wrapper = mount({
+ render () {
+ return
+ },
+ }, {
+ sync: false,
+ attachToDocument: true,
+ })
+ await asyncExpect(() => {
+ wrapper.find('.ant-calendar-picker-input').trigger('click')
+ })
+ await asyncExpect(() => {
+ $$('.ant-calendar-range-quick-selector .ant-tag')[0].click()
+ }, 0)
+ await asyncExpect(() => {
+ expect(handleOpenChange).toBeCalledWith(false)
+ })
+ })
})
diff --git a/components/date-picker/__tests__/__snapshots__/demo.test.js.snap b/components/date-picker/__tests__/__snapshots__/demo.test.js.snap
index 1e6d91c61..6c1e5f529 100644
--- a/components/date-picker/__tests__/__snapshots__/demo.test.js.snap
+++ b/components/date-picker/__tests__/__snapshots__/demo.test.js.snap
@@ -1,30 +1,77 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`renders ./components/date-picker/demo/basic.md correctly 1`] = ``;
-
-exports[`renders ./components/date-picker/demo/date-render.md correctly 1`] = ``;
-
-exports[`renders ./components/date-picker/demo/disabled.md correctly 1`] = ``;
-
-exports[`renders ./components/date-picker/demo/disabled-date.md correctly 1`] = ``;
-
-exports[`renders ./components/date-picker/demo/extra-footer.md correctly 1`] = ``;
-
-exports[`renders ./components/date-picker/demo/format.md correctly 1`] = `
-
+exports[`renders ./components/date-picker/demo/basic.md correctly 1`] = `
+
`;
-exports[`renders ./components/date-picker/demo/mode.md correctly 1`] = ``;
+exports[`renders ./components/date-picker/demo/date-render.md correctly 1`] = `
+
+`;
-exports[`renders ./components/date-picker/demo/presetted-ranges.md correctly 1`] = ` ~
~
`;
+exports[`renders ./components/date-picker/demo/disabled.md correctly 1`] = `
+
+`;
+
+exports[`renders ./components/date-picker/demo/disabled-date.md correctly 1`] = `
+
+`;
+
+exports[`renders ./components/date-picker/demo/extra-footer.md correctly 1`] = `
+
+`;
+
+exports[`renders ./components/date-picker/demo/format.md correctly 1`] = `
+
+`;
+
+exports[`renders ./components/date-picker/demo/mode.md correctly 1`] = `
+
+`;
+
+exports[`renders ./components/date-picker/demo/presetted-ranges.md correctly 1`] = `
+
+`;
exports[`renders ./components/date-picker/demo/size.md correctly 1`] = `
+
~
+
`;
-exports[`renders ./components/date-picker/demo/start-end.md correctly 1`] = ``;
+exports[`renders ./components/date-picker/demo/start-end.md correctly 1`] = ``;
-exports[`renders ./components/date-picker/demo/time.md correctly 1`] = ``;
+exports[`renders ./components/date-picker/demo/suffix.md correctly 1`] = `
+
+`;
+
+exports[`renders ./components/date-picker/demo/time.md correctly 1`] = `
+
+`;
diff --git a/components/date-picker/createPicker.js b/components/date-picker/createPicker.js
index 14ba81bb9..3ed0218c3 100644
--- a/components/date-picker/createPicker.js
+++ b/components/date-picker/createPicker.js
@@ -7,7 +7,8 @@ import classNames from 'classnames'
import Icon from '../icon'
import interopDefault from '../_util/interopDefault'
import BaseMixin from '../_util/BaseMixin'
-import { hasProp, getOptionProps, initDefaultProps, mergeProps } from '../_util/props-util'
+import { hasProp, getOptionProps, initDefaultProps, mergeProps, getComponentFromProp, isValidElement } from '../_util/props-util'
+import { cloneElement } from '../_util/vnode'
// export const PickerProps = {
// value?: moment.Moment;
@@ -44,14 +45,26 @@ export default function createPicker (TheCalendar, props) {
return {
sValue: value,
showDate: value,
+ _open: !!this.open,
}
},
watch: {
+ open (val) {
+ const props = getOptionProps(this)
+ const state = {}
+ state._open = val
+ if ('value' in props && !val && props.value !== this.showDate) {
+ state.showDate = props.value
+ }
+ this.setState(state)
+ },
value (val) {
- this.setState({
- sValue: val,
- showDate: val,
- })
+ const state = {}
+ state.sValue = val
+ if (val !== this.sValue) {
+ state.showDate = val
+ }
+ this.setState(state)
},
},
methods: {
@@ -79,12 +92,19 @@ export default function createPicker (TheCalendar, props) {
})
}
this.$emit('change', value, (value && value.format(this.format)) || '')
+ this.focus()
},
handleCalendarChange (value) {
this.setState({ showDate: value })
},
-
+ handleOpenChange (open) {
+ const props = getOptionProps(this)
+ if (!('open' in props)) {
+ this.setState({ _open: open })
+ }
+ this.$emit('openChange', open)
+ },
focus () {
this.$refs.input.focus()
},
@@ -101,7 +121,10 @@ export default function createPicker (TheCalendar, props) {
},
render () {
- const { sValue: value, showDate, $listeners, $scopedSlots } = this
+ const { $listeners, $scopedSlots } = this
+ const { sValue: value, showDate, _open: open } = this.$data
+ let suffixIcon = getComponentFromProp(this, 'suffixIcon')
+ suffixIcon = Array.isArray(suffixIcon) ? suffixIcon[0] : suffixIcon
const { panelChange = noop, focus = noop, blur = noop, ok = noop } = $listeners
const props = getOptionProps(this)
const { prefixCls, locale, localeCode } = props
@@ -123,9 +146,11 @@ export default function createPicker (TheCalendar, props) {
const pickerProps = { props: {}, on: {}}
const calendarProps = { props: {}, on: {}}
+ const pickerStyle = {}
if (props.showTime) {
// fix https://github.com/ant-design/ant-design/issues/1902
calendarProps.on.select = this.handleChange
+ pickerStyle.width = '195px'
} else {
pickerProps.on.change = this.handleChange
}
@@ -150,7 +175,7 @@ export default function createPicker (TheCalendar, props) {
},
on: {
ok: ok,
- panelChange: panelChange,
+ panelChange,
change: this.handleCalendarChange,
},
class: calendarClassName,
@@ -164,12 +189,24 @@ export default function createPicker (TheCalendar, props) {
const clearIcon = (!props.disabled && props.allowClear && value) ? (
) : null
+ const inputIcon = suffixIcon && (
+ isValidElement(suffixIcon)
+ ? cloneElement(
+ suffixIcon,
+ {
+ class: `${prefixCls}-picker-icon`,
+ },
+ ) : {suffixIcon}) || (
+
+ )
+
const input = ({ value: inputValue }) => (
{clearIcon}
-
+ {inputIcon}
)
const vcDatePickerProps = {
@@ -197,12 +234,15 @@ export default function createPicker (TheCalendar, props) {
on: {
...omit($listeners, 'change'),
...pickerProps.on,
+ open,
+ onOpenChange: this.handleOpenChange,
},
style: props.popupStyle,
}
return (
-
+
diff --git a/components/date-picker/demo/suffix.md b/components/date-picker/demo/suffix.md
new file mode 100644
index 000000000..984a7418c
--- /dev/null
+++ b/components/date-picker/demo/suffix.md
@@ -0,0 +1,51 @@
+
+
+#### 后缀图标
+最简单的用法,在浮层中可以选择或者输入日期。
+
+
+
+#### Suffix
+Basic use case. Users can select or input a date in panel.
+
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+
diff --git a/components/date-picker/index.en-US.md b/components/date-picker/index.en-US.md
index a3ebc9152..05303450c 100644
--- a/components/date-picker/index.en-US.md
+++ b/components/date-picker/index.en-US.md
@@ -37,11 +37,14 @@ The following APIs are shared by DatePicker, MonthPicker, RangePicker, WeekPicke
| popupStyle | to customize the style of the popup calendar | object | {} |
| dropdownClassName | to customize the className of the popup calendar | string | - |
| size | determine the size of the input box, the height of `large` and `small`, are 40px and 24px respectively, while default size is 32px | string | - |
+| suffixIcon | The custom suffix icon | VNode \| slot | - |
### Common Events
| Events Name | Description | Arguments |
| --- | --- | --- |
| openChange | a callback function, can be executed whether the popup calendar is popped up or closed | function(status) |
+| panelChange | callback when picker panel mode is changed | function(value, mode) |
+
### Common Methods
@@ -105,7 +108,7 @@ The following APIs are shared by DatePicker, MonthPicker, RangePicker, WeekPicke
| defaultValue | to set default date | \[[moment](http://momentjs.com/), [moment](http://momentjs.com/)] | - |
| disabledTime | to specify the time that cannot be selected | function(dates: [moment, moment], partial: `'start'|'end'`) | - |
| format | to set the date format | string | "YYYY-MM-DD HH:mm:ss" |
-| ranges | preseted ranges for quick selection | { \[range: string\]: [moment](http://momentjs.com/)\[] } \| () => { \[range: string\]: [moment](http://momentjs.com/)\[] } | - |
+| ranges | preseted ranges for quick selection | { \[range: string]: [moment](http://momentjs.com/)\[] } \| { \[range: string]: () => [moment](http://momentjs.com/)\[] } | - |
| renderExtraFooter | render extra footer in panel by setting a scoped slot| slot="renderExtraFooter" | - |
| showTime | to provide an additional time selection | object\|boolean | [TimePicker Options](/ant-design-vue/components/time-picker/#API) |
| showTime.defaultValue | to set default time of selected date, [demo](https://ant.design/components/date-picker/#components-date-picker-demo-disabled-date) | [moment](http://momentjs.com/)\[] | [moment(), moment()] |
@@ -114,6 +117,7 @@ The following APIs are shared by DatePicker, MonthPicker, RangePicker, WeekPicke
### RangePicker Events
| Events Name | Description | Arguments |
| --- | --- | --- |
+| calendarChange | a callback function, can be executed when the start time or the end time of the range is changing | function(dates: [moment, moment], dateStrings: [string, string]) |
| change | a callback function, can be executed when the selected time is changing | function(dates: [moment, moment], dateStrings: [string, string]) |
| ok | callback when click ok button | function() |
diff --git a/components/date-picker/index.zh-CN.md b/components/date-picker/index.zh-CN.md
index 4bd9928fe..9ff933b2a 100644
--- a/components/date-picker/index.zh-CN.md
+++ b/components/date-picker/index.zh-CN.md
@@ -12,9 +12,9 @@
````html
// 默认语言为 en-US,如果你需要设置其他语言,推荐在入口文件全局设置 locale
-// import moment from 'moment';
-// import 'moment/locale/zh-cn';
-// moment.locale('zh-cn');
+import moment from 'moment';
+import 'moment/locale/zh-cn';
+moment.locale('zh-cn');
````
@@ -37,12 +37,14 @@
| popupStyle | 额外的弹出日历样式 | object | {} |
| dropdownClassName | 额外的弹出日历 className | string | - |
| size | 输入框大小,`large` 高度为 40px,`small` 为 24px,默认是 32px | string | 无 |
+| suffixIcon | 自定义的选择框后缀图标 | VNode \| slot | - |
### 共有的事件
| 事件名称 | 说明 | 回调参数 |
| --- | --- | --- |
| openChange | 弹出日历和关闭日历的回调 | function(status) |
+| panelChange | 日期面板变化时的回调 | function(value, mode) | - |
### 共同的方法
@@ -108,7 +110,7 @@
| defaultValue | 默认日期 | [moment](http://momentjs.com/)\[] | 无 |
| disabledTime | 不可选择的时间 | function(dates: [moment, moment], partial: `'start'|'end'`) | 无 |
| format | 展示的日期格式 | string | "YYYY-MM-DD HH:mm:ss" |
-| ranges | 预设时间范围快捷选择 | { \[range: string\]: [moment](http://momentjs.com/)\[] } \| () => { \[range: string\]: [moment](http://momentjs.com/)\[] } | 无 |
+| ranges | 预设时间范围快捷选择 | { \[range: string]: [moment](http://momentjs.com/)\[] } \| { \[range: string]: () => [moment](http://momentjs.com/)\[] } | 无 |
| renderExtraFooter | 在面板中添加额外的页脚 | slot="renderExtraFooter" | - |
| showTime | 增加时间选择功能 | Object\|boolean | [TimePicker Options](/ant-design-vue/components/time-picker-cn/#API) |
| showTime.defaultValue | 设置用户选择日期时默认的时分秒 | [moment](http://momentjs.com/)\[] | [moment(), moment()] |
diff --git a/components/date-picker/interface.js b/components/date-picker/interface.js
index 5c3929341..9a4321341 100644
--- a/components/date-picker/interface.js
+++ b/components/date-picker/interface.js
@@ -16,6 +16,7 @@ export const PickerProps = () => ({
format: PropTypes.string,
disabled: PropTypes.bool,
allowClear: PropTypes.bool,
+ suffixIcon: PropTypes.any,
popupStyle: PropTypes.object,
dropdownClassName: PropTypes.string,
locale: PropTypes.any,
diff --git a/components/date-picker/locale/mn_MN.js b/components/date-picker/locale/mn_MN.js
new file mode 100644
index 000000000..485403126
--- /dev/null
+++ b/components/date-picker/locale/mn_MN.js
@@ -0,0 +1,19 @@
+import CalendarLocale from '../../vc-calendar/src/locale/mn_MN'
+import TimePickerLocale from '../../time-picker/locale/mn_MN'
+
+// Merge into a locale object
+const locale = {
+ lang: {
+ placeholder: 'Огноо сонгох',
+ rangePlaceholder: ['Эхлэх огноо', 'Дуусах огноо'],
+ ...CalendarLocale,
+ },
+ timePickerLocale: {
+ ...TimePickerLocale,
+ },
+}
+
+// All settings at:
+// https://github.com/ant-design/ant-design/blob/master/components/date-picker/locale/example.json
+
+export default locale
diff --git a/components/date-picker/locale/vi_VN.js b/components/date-picker/locale/vi_VN.js
index 65fe299a8..9219e73e9 100644
--- a/components/date-picker/locale/vi_VN.js
+++ b/components/date-picker/locale/vi_VN.js
@@ -1,5 +1,5 @@
-import CalendarLocale from '../../vc-calendar/src/locale/en_US'
-import TimePickerLocale from '../../time-picker/locale/en_US'
+import CalendarLocale from '../../vc-calendar/src/locale/vi_VN'
+import TimePickerLocale from '../../time-picker/locale/vi_VN'
// Merge into a locale object
const locale = {
diff --git a/components/date-picker/wrapPicker.js b/components/date-picker/wrapPicker.js
index 144b6937f..de359f531 100644
--- a/components/date-picker/wrapPicker.js
+++ b/components/date-picker/wrapPicker.js
@@ -1,4 +1,3 @@
-
import TimePickerPanel from '../vc-time-picker/Panel'
import classNames from 'classnames'
import LocaleReceiver from '../locale-provider/LocaleReceiver'
@@ -147,9 +146,11 @@ export default function wrapPicker (Picker, props, defaultFormat) {
-
- {this.$slots.renderExtraFooter}
-
+ {this.$slots && Object.keys(this.$slots).map(key => (
+
+ {this.$slots[key]}
+
+ ))}
)
},