Browse Source

DatePicker: extract time and date format from format prop (#10174)

remizovvv 7 years ago
parent
commit
bfa44e8b4f

+ 1 - 1
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 | — | {} |

+ 14 - 12
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,34 +274,34 @@
       },
 
       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) : '';
       },
 
-      dateFormat() {
+      timeFormat() {
         if (this.format) {
-          return this.format.replace('HH:mm', '').replace(':ss', '').trim();
+          return extractTimeFormat(this.format);
         } else {
-          return 'yyyy-MM-dd';
+          return 'HH:mm:ss';
         }
       },
 
-      timeFormat() {
-        if (this.format && this.format.indexOf('ss') === -1) {
-          return 'HH:mm';
+      dateFormat() {
+        if (this.format) {
+          return extractDateFormat(this.format);
         } else {
-          return 'HH:mm:ss';
+          return 'yyyy-MM-dd';
         }
       },
 

+ 6 - 5
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';
         }

+ 8 - 3
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 });

+ 13 - 0
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();
+};

+ 93 - 0
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: '<el-date-picker type="datetime" v-model="value" :format="format" :pickerOptions="pickerOptions" ref="compo" />',
+        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: '<el-date-picker type="datetime" v-model="value" ref="compo" />',
@@ -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: `
+          <el-date-picker ref="compo" type="datetimerange" v-model="value" :format="format"></el-date-picker>
+        `,
+        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({