Browse Source

DatePicker: validate input date (#12898)

* date-picker: fix confirm() ignoring date validity

make date-range panel's confirm validate date before confirming.

1. disable confirm button if picked date is invalid
2. reset highlight date on picker open (resetView)

* test: date-time-range confirm honors disabledDate
Jiewei Qian 6 years ago
parent
commit
6cb92acc34
2 changed files with 50 additions and 5 deletions
  1. 13 3
      packages/date-picker/src/panel/date-range.vue
  2. 37 2
      test/unit/specs/date-picker.spec.js

+ 13 - 3
packages/date-picker/src/panel/date-range.vue

@@ -176,7 +176,7 @@
           size="mini"
           class="el-picker-panel__link-btn"
           :disabled="btnDisabled"
-          @click="handleConfirm()">
+          @click="handleConfirm(false)">
           {{ t('el.datepicker.confirm') }}
         </el-button>
       </div>
@@ -227,7 +227,7 @@
 
     computed: {
       btnDisabled() {
-        return !(this.minDate && this.maxDate && !this.selecting);
+        return !(this.minDate && this.maxDate && !this.selecting && this.isValidValue([this.minDate, this.maxDate]));
       },
 
       leftLabel() {
@@ -610,7 +610,9 @@
       },
 
       handleConfirm(visible = false) {
-        this.$emit('pick', [this.minDate, this.maxDate], visible);
+        if (this.isValidValue([this.minDate, this.maxDate])) {
+          this.$emit('pick', [this.minDate, this.maxDate], visible);
+        }
       },
 
       isValidValue(value) {
@@ -622,6 +624,14 @@
             ? !this.disabledDate(value[0]) && !this.disabledDate(value[1])
             : true
         );
+      },
+
+      resetView() {
+        // NOTE: this is a hack to reset {min, max}Date on picker open.
+        // TODO: correct way of doing so is to refactor {min, max}Date to be dependent on value and internal selection state
+        //       an alternative would be resetView whenever picker becomes visible, should also investigate date-panel's resetView
+        this.minDate = this.value && isDate(this.value[0]) ? new Date(this.value[0]) : null;
+        this.maxDate = this.value && isDate(this.value[0]) ? new Date(this.value[1]) : null;
       }
     },
 

+ 37 - 2
test/unit/specs/date-picker.spec.js

@@ -1760,7 +1760,6 @@ describe('DatePicker', () => {
             picker.$el.querySelector('td.available ~ td.available').click();
             setTimeout(_ => {
               expect(spy.calledOnce).to.equal(true);
-              console.log('first assert passed');
               // change event is not emitted if used does not change value
               // datarange also requires proper array equality check
               input.blur();
@@ -1773,7 +1772,6 @@ describe('DatePicker', () => {
                   endCell.click();
                   setTimeout(_ => {
                     expect(spy.calledOnce).to.equal(true);
-                    console.log('second assert passed');
                     done();
                   }, DELAY);
                 }, DELAY);
@@ -2194,6 +2192,43 @@ describe('DatePicker', () => {
         }, DELAY);
       }, DELAY);
     });
+
+    it('confirm honors disabledDate', done => {
+      vm = createVue({
+        template: '<el-date-picker type="datetimerange" value-format="yyyy-MM-dd HH:mm:ss" v-model="value" :picker-options="pickerOptions" ref="compo" />',
+        data() {
+          return {
+            pickerOptions: {
+              disabledDate(date) {
+                return date.getTime() < new Date(2000, 9, 1); // 2000-10-01
+              }
+            },
+            value: ['2000-10-02 00:00:00', '2000-10-03 00:00:00']
+          };
+        }
+      }, true);
+      const input = vm.$el.querySelector('input');
+
+      input.blur();
+      input.focus();
+      setTimeout(_ => {
+        // simulate user input of invalid date
+        vm.$refs.compo.picker.handleDateChange({ target: { value: '2000-09-01'} }, 'min');
+        setTimeout(_ => {
+          expect(vm.$refs.compo.picker.btnDisabled).to.equal(true); // invalid input disables button
+          vm.$refs.compo.picker.handleConfirm();
+          setTimeout(_ => {
+            expect(vm.$refs.compo.pickerVisible).to.equal(true); // can not confirm, picker remains open
+            // simulate click outside to close picker
+            vm.$refs.compo.handleClose();
+            setTimeout(_ => {
+              expect(vm.value).to.eql(['2000-10-02 00:00:00', '2000-10-03 00:00:00']);
+              done();
+            }, DELAY);
+          }, DELAY);
+        }, DELAY);
+      }, DELAY);
+    });
   });
 
   const currentMonth = new Date(new Date().getTime());