2
0
mirror of https://github.com/tenrok/vue2-datepicker.git synced 2026-06-23 04:40:37 +03:00

Merge branch 'origin/dev' into dev

This commit is contained in:
mengxiong10
2020-06-07 11:23:05 +08:00
7 changed files with 98 additions and 14 deletions
+2
View File
@@ -124,6 +124,7 @@ You can also override some of the default locale by `lang`.
| clearable | if false, don't show the clear icon | `boolean` | true | | clearable | if false, don't show the clear icon | `boolean` | true |
| confirm | if true, need click the button to change value | `boolean` | false | | confirm | if true, need click the button to change value | `boolean` | false |
| confirm-text | the text of confirm button | `string` | 'OK' | | confirm-text | the text of confirm button | `string` | 'OK' |
| multiple | if true, multi-select date | `boolean` | false |
| disabled | disable the component | `boolean` | false | | disabled | disable the component | `boolean` | false |
| disabled-date | specify the date that cannot be selected | `(date) => boolean` | - | | disabled-date | specify the date that cannot be selected | `(date) => boolean` | - |
| disabled-time | specify the time that cannot be selected | `(date) => boolean` | - | | disabled-time | specify the time that cannot be selected | `(date) => boolean` | - |
@@ -132,6 +133,7 @@ You can also override some of the default locale by `lang`.
| input-class | input classname | `string` | 'mx-input' | | input-class | input classname | `string` | 'mx-input' |
| input-attr | input attrs(eg: { name: 'date', id: 'foo'}) | `object` | — | | input-attr | input attrs(eg: { name: 'date', id: 'foo'}) | `object` | — |
| open | open state of picker | `boolean` | - | | open | open state of picker | `boolean` | - |
| default-panel | default panel of the picker | year\|month | - |
| popup-style | popup style | `object` | — | | popup-style | popup style | `object` | — |
| popup-class | popup classes | | — | | popup-class | popup classes | | — |
| shortcuts | set shortcuts to select | `Array<{text, onClick}>` | - | | shortcuts | set shortcuts to select | `Array<{text, onClick}>` | - |
+2
View File
@@ -122,6 +122,7 @@ import 'vue2-datepicker/locale/zh-cn';
| clearable | 是否显示清除按钮 | `boolean` | true | | clearable | 是否显示清除按钮 | `boolean` | true |
| confirm | 是否需要确认 | `boolean` | false | | confirm | 是否需要确认 | `boolean` | false |
| confirm-text | 确认按钮的文字 | `string` | 'OK' | | confirm-text | 确认按钮的文字 | `string` | 'OK' |
| multiple | 如果是 true, 可以选择多个日期 | `boolean` | false |
| disabled | 禁用组件 | `boolean` | false | | disabled | 禁用组件 | `boolean` | false |
| disabled-date | 禁止选择的日期 | `(date) => boolean` | - | | disabled-date | 禁止选择的日期 | `(date) => boolean` | - |
| disabled-time | 禁止选择的时间 | `(date) => boolean` | - | | disabled-time | 禁止选择的时间 | `(date) => boolean` | - |
@@ -130,6 +131,7 @@ import 'vue2-datepicker/locale/zh-cn';
| input-class | 输入框的类 | `string` | 'mx-input' | | input-class | 输入框的类 | `string` | 'mx-input' |
| input-attr | 输入框的其他属性(eg: { name: 'date', id: 'foo'}) | `object` | — | | input-attr | 输入框的其他属性(eg: { name: 'date', id: 'foo'}) | `object` | — |
| open | 控制弹出层的显示 | `boolean` | - | | open | 控制弹出层的显示 | `boolean` | - |
| default-panel | 控制打开的面板 | year\|month | - |
| popup-style | 弹出层的样式 | `object` | — | | popup-style | 弹出层的样式 | `object` | — |
| popup-class | 弹出层的类 | | — | | popup-class | 弹出层的类 | | — |
| shortcuts | 设置快捷选择 | `Array<{text, onClick}>` | - | | shortcuts | 设置快捷选择 | `Array<{text, onClick}>` | - |
+31
View File
@@ -387,4 +387,35 @@ describe('DatePicker', () => {
input.trigger('change'); input.trigger('change');
expect(wrapper.emitted().input).toEqual([[[text, text]], [[text, text]], [[text, text]]]); expect(wrapper.emitted().input).toEqual([[[text, text]], [[text, text]], [[text, text]]]);
}); });
it('prop: multiple', () => {
const value = [new Date(2020, 5, 6), new Date(2020, 6, 7)];
wrapper = mount(DatePicker, {
propsData: {
multiple: true,
open: true,
value,
},
});
wrapper.find('.mx-date-row .active').trigger('click');
expect(wrapper.emitted().input[0][0]).toEqual(value.slice(0, 1));
wrapper.find('[title="2020-07-15"]').trigger('click');
expect(wrapper.emitted().input[1][0]).toEqual(value.concat(new Date(2020, 6, 15)));
});
it('prop: invalid multiple', () => {
wrapper = shallowMount(DatePicker, {
propsData: {
multiple: true,
range: true,
},
});
const { vm } = wrapper;
expect(vm.validMultipleType).toBe(false);
wrapper.setProps({
range: false,
type: 'datetime',
});
expect(vm.validMultipleType).toBe(false);
});
}); });
-2
View File
@@ -38,10 +38,8 @@ export default {
data() { data() {
return { return {
value1: new Date(), value1: new Date(),
value2: new Date(),
value3: '', value3: '',
value4: '', value4: '',
value5: '',
}; };
}, },
methods: { methods: {
+5 -4
View File
@@ -240,7 +240,8 @@ export default {
initCalendar() { initCalendar() {
let calendarDate = this.calendar; let calendarDate = this.calendar;
if (!isValidDate(calendarDate)) { if (!isValidDate(calendarDate)) {
calendarDate = getValidDate(this.innerValue[0], this.defaultValue); const { length } = this.innerValue;
calendarDate = getValidDate(length > 0 ? this.innerValue[length - 1] : this.defaultValue);
} }
this.innerCalendar = calendarDate; this.innerCalendar = calendarDate;
}, },
@@ -249,7 +250,7 @@ export default {
}, },
emitDate(date, type) { emitDate(date, type) {
if (!this.isDisabled(date)) { if (!this.isDisabled(date)) {
this.$emit('select', date, type); this.$emit('select', date, type, this.innerValue);
// someone need get the first selected date to set range value. (#429) // someone need get the first selected date to set range value. (#429)
this.dispatch('DatePicker', 'pick', date, type); this.dispatch('DatePicker', 'pick', date, type);
} }
@@ -287,7 +288,7 @@ export default {
const nextCalendar = setYear(this.innerCalendar, year); const nextCalendar = setYear(this.innerCalendar, year);
this.updateCalendar(nextCalendar, 'year'); this.updateCalendar(nextCalendar, 'year');
this.handelPanelChange('month'); this.handelPanelChange('month');
if (this.partialUpdate && this.innerValue[0]) { if (this.partialUpdate && this.innerValue.length === 1) {
const date = setYear(this.innerValue[0], year); const date = setYear(this.innerValue[0], year);
this.emitDate(date, 'year'); this.emitDate(date, 'year');
} }
@@ -301,7 +302,7 @@ export default {
const nextCalendar = setMonth(this.innerCalendar, month); const nextCalendar = setMonth(this.innerCalendar, month);
this.updateCalendar(nextCalendar, 'month'); this.updateCalendar(nextCalendar, 'month');
this.handelPanelChange('date'); this.handelPanelChange('date');
if (this.partialUpdate && this.innerValue[0]) { if (this.partialUpdate && this.innerValue.length === 1) {
const date = setMonth(setYear(this.innerValue[0], this.calendarYear), month); const date = setMonth(setYear(this.innerValue[0], this.calendarYear), month);
this.emitDate(date, 'month'); this.emitDate(date, 'month');
} }
+47 -7
View File
@@ -90,7 +90,7 @@
<script> <script>
import { parse, format, getWeek } from 'date-format-parse'; import { parse, format, getWeek } from 'date-format-parse';
import { isValidDate, isValidRangeDate } from './util/date'; import { isValidDate, isValidRangeDate, isValidDates } from './util/date';
import { pick, isObject, mergeDeep } from './util/base'; import { pick, isObject, mergeDeep } from './util/base';
import { getLocale, getLocaleFieldValue } from './locale'; import { getLocale, getLocaleFieldValue } from './locale';
import Popup from './popup'; import Popup from './popup';
@@ -157,9 +157,15 @@ export default {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
multiple: {
type: Boolean,
default: false,
},
rangeSeparator: { rangeSeparator: {
type: String, type: String,
default: ' ~ ', default() {
return this.multiple ? ',' : ' ~ ';
},
}, },
lang: { lang: {
type: [String, Object], type: [String, Object],
@@ -222,6 +228,9 @@ export default {
type: String, type: String,
default: 'OK', default: 'OK',
}, },
renderInputText: {
type: Function,
},
shortcuts: { shortcuts: {
type: Array, type: Array,
validator(value) { validator(value) {
@@ -262,6 +271,10 @@ export default {
}, },
innerValue() { innerValue() {
let { value } = this; let { value } = this;
if (this.validMultipleType) {
value = Array.isArray(value) ? value : [];
return value.map(this.value2date);
}
if (this.range) { if (this.range) {
value = Array.isArray(value) ? value.slice(0, 2) : [null, null]; value = Array.isArray(value) ? value.slice(0, 2) : [null, null];
return value.map(this.value2date); return value.map(this.value2date);
@@ -272,6 +285,9 @@ export default {
if (this.userInput !== null) { if (this.userInput !== null) {
return this.userInput; return this.userInput;
} }
if (typeof this.renderInputText === 'function') {
return this.renderInputText(this.innerValue);
}
if (!this.isValidValue(this.innerValue)) { if (!this.isValidValue(this.innerValue)) {
return ''; return '';
} }
@@ -290,6 +306,10 @@ export default {
} }
return getLocale(this.lang); return getLocale(this.lang);
}, },
validMultipleType() {
const types = ['date', 'month', 'year'];
return this.multiple && !this.range && types.indexOf(this.type) !== -1;
},
}, },
watch: { watch: {
innerValue: { innerValue: {
@@ -368,14 +388,30 @@ export default {
} }
}, },
isValidValue(value) { isValidValue(value) {
const validate = this.range ? isValidRangeDate : isValidDate; if (this.validMultipleType) {
return validate(value); return isValidDates(value);
}
if (this.range) {
return isValidRangeDate(value);
}
return isValidDate(value);
}, },
handleSelectDate(val, type) { handleMultipleDates(date, dates) {
if (this.validMultipleType && dates) {
const nextDates = dates.filter(v => v.getTime() !== date.getTime());
if (nextDates.length === dates.length) {
nextDates.push(date);
}
return nextDates;
}
return date;
},
handleSelectDate(val, type, dates) {
val = this.handleMultipleDates(val, dates);
if (this.confirm) { if (this.confirm) {
this.currentValue = val; this.currentValue = val;
} else { } else {
this.emitValue(val, type); this.emitValue(val, this.validMultipleType ? `multiple-${type}` : type);
} }
}, },
handleClear() { handleClear() {
@@ -421,9 +457,13 @@ export default {
return; return;
} }
let date; let date;
if (this.range) { if (this.validMultipleType) {
date = text.split(this.rangeSeparator).map(v => this.parseDate(v.trim(), this.format));
} else if (this.range) {
let arr = text.split(this.rangeSeparator); let arr = text.split(this.rangeSeparator);
if (arr.length !== 2) { if (arr.length !== 2) {
// Maybe the separator during the day is the same as the separator for the date
// eg: 2019-10-09-2020-01-02
arr = text.split(this.rangeSeparator.trim()); arr = text.split(this.rangeSeparator.trim());
} }
date = arr.map(v => this.parseDate(v.trim(), this.format)); date = arr.map(v => this.parseDate(v.trim(), this.format));
+11 -1
View File
@@ -15,9 +15,19 @@ export function isValidRangeDate(date) {
return Array.isArray(date) && date.length === 2 && date.every(isValidDate) && date[0] <= date[1]; return Array.isArray(date) && date.length === 2 && date.every(isValidDate) && date[0] <= date[1];
} }
export function isValidDates(dates) {
return Array.isArray(dates) && dates.every(isValidDate);
}
export function getValidDate(value, ...backup) { export function getValidDate(value, ...backup) {
const date = new Date(value); const date = new Date(value);
return isValidDate(date) ? date : getValidDate(...backup); if (isValidDate(date)) {
return date;
}
if (backup.length) {
return getValidDate(...backup);
}
return new Date();
} }
export function assignTime(target, source) { export function assignTime(target, source) {