diff --git a/examples/docs/en-US/datetime-picker.md b/examples/docs/en-US/datetime-picker.md index 615e6083e..84da00db2 100644 --- a/examples/docs/en-US/datetime-picker.md +++ b/examples/docs/en-US/datetime-picker.md @@ -278,7 +278,7 @@ DateTimePicker is derived from DatePicker and TimePicker. For a more detailed ex | end-placeholder | placeholder for the end date in range mode | string | — | — | | time-arrow-control | whether to pick time using arrow buttons | boolean | — | false | | type | type of the picker | string | year/month/date/datetime/ week/datetimerange/daterange | date | -| format | format of the displayed value in the input box | string | see [date formats](#/en-US/component/date-picker#date-formats) | yyyy-MM-dd | +| format | format of the displayed value in the input box | string | see [date formats](#/en-US/component/date-picker#date-formats) | yyyy-MM-dd HH:mm:ss | | align | alignment | left/center/right | left | | popper-class | custom class name for DateTimePicker's dropdown | string | — | — | | picker-options | additional options, check the table below | object | — | {} | diff --git a/packages/date-picker/src/panel/date-range.vue b/packages/date-picker/src/panel/date-range.vue index 6a6af98e4..0041c0eeb 100644 --- a/packages/date-picker/src/panel/date-range.vue +++ b/packages/date-picker/src/panel/date-range.vue @@ -193,7 +193,9 @@ prevYear, nextYear, prevMonth, - nextMonth + nextMonth, + extractDateFormat, + extractTimeFormat } from '../util'; import Clickoutside from 'element-ui/src/utils/clickoutside'; import Locale from 'element-ui/src/mixins/locale'; @@ -272,37 +274,37 @@ }, minVisibleDate() { - return this.minDate ? formatDate(this.minDate) : ''; + return this.minDate ? formatDate(this.minDate, this.dateFormat) : ''; }, maxVisibleDate() { - return (this.maxDate || this.minDate) ? formatDate(this.maxDate || this.minDate) : ''; + return (this.maxDate || this.minDate) ? formatDate(this.maxDate || this.minDate, this.dateFormat) : ''; }, minVisibleTime() { - return this.minDate ? formatDate(this.minDate, 'HH:mm:ss') : ''; + return this.minDate ? formatDate(this.minDate, this.timeFormat) : ''; }, maxVisibleTime() { - return (this.maxDate || this.minDate) ? formatDate(this.maxDate || this.minDate, 'HH:mm:ss') : ''; + return (this.maxDate || this.minDate) ? formatDate(this.maxDate || this.minDate, this.timeFormat) : ''; + }, + + timeFormat() { + if (this.format) { + return extractTimeFormat(this.format); + } else { + return 'HH:mm:ss'; + } }, dateFormat() { if (this.format) { - return this.format.replace('HH:mm', '').replace(':ss', '').trim(); + return extractDateFormat(this.format); } else { return 'yyyy-MM-dd'; } }, - timeFormat() { - if (this.format && this.format.indexOf('ss') === -1) { - return 'HH:mm'; - } else { - return 'HH:mm:ss'; - } - }, - enableMonthArrow() { const nextMonth = (this.leftMonth + 1) % 12; const yearOffset = this.leftMonth + 1 >= 12 ? 1 : 0; diff --git a/packages/date-picker/src/panel/date.vue b/packages/date-picker/src/panel/date.vue index bb2f56efa..984e4f5ba 100644 --- a/packages/date-picker/src/panel/date.vue +++ b/packages/date-picker/src/panel/date.vue @@ -153,7 +153,9 @@ nextYear, prevMonth, nextMonth, - changeYearMonthAndClampDate + changeYearMonthAndClampDate, + extractDateFormat, + extractTimeFormat } from '../util'; import Clickoutside from 'element-ui/src/utils/clickoutside'; import Locale from 'element-ui/src/mixins/locale'; @@ -215,7 +217,6 @@ const value = value => {this.$refs.timepicker.value = value;}; const date = date => {this.$refs.timepicker.date = date;}; - this.$watch('format', format); this.$watch('value', value); this.$watch('date', date); @@ -523,8 +524,8 @@ }, timeFormat() { - if (this.format && this.format.indexOf('ss') === -1) { - return 'HH:mm'; + if (this.format) { + return extractTimeFormat(this.format); } else { return 'HH:mm:ss'; } @@ -532,7 +533,7 @@ dateFormat() { if (this.format) { - return this.format.replace('HH', '').replace(/[^a-zA-Z]*mm/, '').replace(/[^a-zA-Z]*ss/, '').trim(); + return extractDateFormat(this.format); } else { return 'yyyy-MM-dd'; } diff --git a/packages/date-picker/src/picker.vue b/packages/date-picker/src/picker.vue index 6977b3a5b..9cb35f059 100644 --- a/packages/date-picker/src/picker.vue +++ b/packages/date-picker/src/picker.vue @@ -747,9 +747,9 @@ export default { this.picker.selectionMode = this.selectionMode; this.picker.unlinkPanels = this.unlinkPanels; this.picker.arrowControl = this.arrowControl || this.timeArrowControl || false; - if (this.format) { - this.picker.format = this.format; - } + this.$watch('format', (format) => { + this.picker.format = format; + }); const updateOptions = () => { const options = this.pickerOptions; @@ -770,6 +770,11 @@ export default { this.picker[option] = options[option]; } } + + // main format must prevail over undocumented pickerOptions.format + if (this.format) { + this.picker.format = this.format; + } }; updateOptions(); this.unwatchPickerOptions = this.$watch('pickerOptions', () => updateOptions(), { deep: true }); diff --git a/packages/date-picker/src/util/index.js b/packages/date-picker/src/util/index.js index f9440088f..8145c893e 100644 --- a/packages/date-picker/src/util/index.js +++ b/packages/date-picker/src/util/index.js @@ -215,3 +215,16 @@ export const nextYear = function(date, amount = 1) { const month = date.getMonth(); return changeYearMonthAndClampDate(date, year + amount, month); }; + +export const extractDateFormat = function(format) { + return format + .replace(/\W?m{1,2}|\W?ZZ/g, '') + .replace(/\W?h{1,2}|\W?s{1,3}|\W?a/gi, '') + .trim(); +}; + +export const extractTimeFormat = function(format) { + return format + .replace(/\W?D{1,2}|\W?Do|\W?d{1,4}|\W?M{1,4}|\W?y{2,4}/g, '') + .trim(); +}; diff --git a/test/unit/specs/date-picker.spec.js b/test/unit/specs/date-picker.spec.js index a3e26461c..3be54605d 100644 --- a/test/unit/specs/date-picker.spec.js +++ b/test/unit/specs/date-picker.spec.js @@ -967,6 +967,49 @@ describe('DatePicker', () => { expect(vm.picker.$el.querySelector('.el-time-panel')).to.ok; }); + it('both picker show correct formated value (extract date-format and time-format from format property)', done => { + vm = createVue({ + template: '', + data() { + return { + value: new Date(2018, 2, 5, 10, 15, 24), + format: 'yyyy/MM/dd hh:mm A', + pickerOptions: null + }; + } + }, true); + + const input = vm.$refs.compo.$el.querySelector('input'); + input.blur(); + input.focus(); + setTimeout(_ => { + const datePanel = vm.$refs.compo.picker; + const dateInput = datePanel.$el.querySelector('.el-date-picker__time-header > span:nth-child(1) input'); + const timeInput = datePanel.$el.querySelector('.el-date-picker__time-header > span:nth-child(2) input'); + timeInput.focus(); + setTimeout(_ => { + // both input shows correct value + expect(dateInput.value).to.equal('2018/03/05'); + expect(timeInput.value).to.equal('10:15 AM'); + + // change main format + vm.format = 'd-M-yy hh a'; + setTimeout(_ => { + expect(dateInput.value).to.equal('5-3-18'); + expect(timeInput.value).to.equal('10 am'); + + // change not documented pickerOptions.format mustn't change picker format + vm.pickerOptions = { format: 'yyyy-MM-dd HH:mm:ss'}; + setTimeout(_ => { + expect(dateInput.value).to.equal('5-3-18'); + expect(timeInput.value).to.equal('10 am'); + done(); + }, DELAY); + }, DELAY); + }, DELAY); + }, DELAY); + }); + it('both picker show correct value', done => { vm = createVue({ template: '', @@ -1634,6 +1677,56 @@ describe('DatePicker', () => { }, DELAY); }); + it('both picker show correct formated value (extract date-format and time-format from format property)', done => { + destroyVM(vm); // nuke beforeEach's vm before creating our own + vm = createVue({ + template: ` + + `, + data() { + return { + value: [new Date(2018, 8, 5, 10, 20, 30), new Date(2018, 8, 15, 15, 35, 45)], + format: 'yyyy/MM/dd hh:mm A' + }; + } + }, true); + + setTimeout(_ => { + const compo = vm.$refs.compo; + compo.$el.click(); + setTimeout(_ => { + const pickers = compo.picker.$el.querySelectorAll('.el-date-range-picker__time-header .el-date-range-picker__editors-wrap'); + const left = { + dateInput: pickers[0].querySelector('.el-date-range-picker__time-picker-wrap:nth-child(1) input'), + timeInput: pickers[0].querySelector('.el-date-range-picker__time-picker-wrap:nth-child(2) input') + }; + const right = { + dateInput: pickers[1].querySelector('.el-date-range-picker__time-picker-wrap:nth-child(1) input'), + timeInput: pickers[1].querySelector('.el-date-range-picker__time-picker-wrap:nth-child(2) input') + }; + left.timeInput.focus(); + right.timeInput.focus(); + + // all inputs shows correct value + expect(left.dateInput.value).to.equal('2018/09/05'); + expect(left.timeInput.value).to.equal('10:20 AM'); + expect(right.dateInput.value).to.equal('2018/09/15'); + expect(right.timeInput.value).to.equal('03:35 PM'); + + vm.format = 'd-M-yy HH:mm:ss'; + setTimeout(_ => { + expect(left.dateInput.value).to.equal('5-9-18'); + expect(left.timeInput.value).to.equal('10:20:30'); + expect(right.dateInput.value).to.equal('15-9-18'); + expect(right.timeInput.value).to.equal('15:35:45'); + + done(); + }, DELAY); + + }, DELAY); + }, DELAY); + }); + it('select daterange with defaultTime min & max', done => { destroyVM(vm); // nuke beforeEach's vm before creating our own vm = createVue({