diff --git a/README.md b/README.md index 2c88187..8426631 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,7 @@ You can also override some of the default locale by `lang`. | popup-class | popup classes | | — | | shortcuts | set shortcuts to select | `Array<{text, onClick}>` | - | | title-format | format of the tooltip in calendar cell | [token](#token) | 'YYYY-MM-DD' | +| partial-update | whether update date when select year or month | `boolean` | false | | range-separator | text of range separator | `string` | ' ~ ' | | show-week-number | determine whether show week number | `boolean` | false | | hour-step | interval between hours in time picker | 1 - 60 | 1 | diff --git a/README.zh-CN.md b/README.zh-CN.md index dccb24c..bcf11bf 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -119,6 +119,7 @@ import 'vue2-datepicker/locale/zh-cn'; | popup-class | 弹出层的类 | | — | | shortcuts | 设置快捷选择 | `Array<{text, onClick}>` | - | | title-format | 日历单元格的 tooltip | [token](#token) | 'YYYY-MM-DD' | +| partial-update | 是否更新日期当选择年或月的时候 | `boolean` | false | | range-separator | 范围分隔符 | `string` | ' ~ ' | | show-week-number | 是否显示星期数字 | `boolean` | false | | hour-step | 小时列的间隔 | 1 - 60 | 1 | diff --git a/__test__/__snapshots__/calendar-panel.test.js.snap b/__test__/__snapshots__/calendar-panel.test.js.snap index 8080560..97832fd 100644 --- a/__test__/__snapshots__/calendar-panel.test.js.snap +++ b/__test__/__snapshots__/calendar-panel.test.js.snap @@ -14,7 +14,7 @@ exports[`CalendarPanel prop: type=date 1`] = ` class="mx-icon-double-left" /> - + - + - + - + - +
@@ -67,12 +67,12 @@ exports[`CalendarPanel prop: type=date 1`] = ` getcellclasses="function () { [native code] }" style="display: none;" /> - + - + - + - + - + - +
- +
@@ -146,11 +146,11 @@ exports[`CalendarPanel prop: type=month 1`] = ` getcellclasses="function () { [native code] }" style="display: none;" /> - + - +
@@ -170,7 +170,7 @@ exports[`CalendarPanel prop: type=year 1`] = ` class="mx-icon-double-left" /> - + - + - + - + 2010 - + - + 2019 - +
@@ -221,9 +221,9 @@ exports[`CalendarPanel prop: type=year 1`] = ` decade="2010" getcellclasses="function () { [native code] }" /> - + - +
diff --git a/__test__/calendar-panel.test.js b/__test__/calendar-panel.test.js index d6f457a..e2a11dd 100644 --- a/__test__/calendar-panel.test.js +++ b/__test__/calendar-panel.test.js @@ -64,43 +64,6 @@ describe('CalendarPanel', () => { expect(td.classes()).toContain('active'); }); - const renderType = type => { - it(`prop: type=${type}`, () => { - wrapper = shallowMount(CalendarPanel, { - propsData: { - type, - value: new Date(2019, 9, 1, 10), - }, - }); - expect(wrapper.element).toMatchSnapshot(); - }); - }; - ['date', 'month', 'year'].forEach(renderType); - - it('prop: disabledDate', () => { - const disabledDate = date => { - return date < new Date(2019, 9, 1) || date > new Date(2019, 9, 20); - }; - wrapper = mount(CalendarPanel, { - propsData: { - value: new Date(2019, 9, 4), - disabledDate, - }, - }); - const tds = wrapper.findAll('.mx-table-date td'); - for (let i = 0; i < 42; i++) { - const td = tds.at(i); - const classes = td.classes(); - if (i < 2 || i > 21) { - expect(classes).toContain('disabled'); - } else { - expect(classes).not.toContain('disabled'); - } - } - tds.at(1).trigger('click'); - expect(wrapper.emitted().select).toBeUndefined(); - }); - it('feat: click prev/next month', () => { wrapper = shallowMount(CalendarPanel); @@ -167,4 +130,61 @@ describe('CalendarPanel', () => { lastBtn.trigger('click'); expect(vm.calendarDecade).toBe(2000); }); + + const renderType = type => { + it(`prop: type=${type}`, () => { + wrapper = shallowMount(CalendarPanel, { + propsData: { + type, + value: new Date(2019, 9, 1, 10), + }, + }); + expect(wrapper.element).toMatchSnapshot(); + }); + }; + ['date', 'month', 'year'].forEach(renderType); + + it('prop: disabledDate', () => { + const disabledDate = date => { + return date < new Date(2019, 9, 1) || date > new Date(2019, 9, 20); + }; + wrapper = mount(CalendarPanel, { + propsData: { + value: new Date(2019, 9, 4), + disabledDate, + }, + }); + const tds = wrapper.findAll('.mx-table-date td'); + for (let i = 0; i < 42; i++) { + const td = tds.at(i); + const classes = td.classes(); + if (i < 2 || i > 21) { + expect(classes).toContain('disabled'); + } else { + expect(classes).not.toContain('disabled'); + } + } + tds.at(1).trigger('click'); + expect(wrapper.emitted().select).toBeUndefined(); + }); + + it('prop: partialUpdate', () => { + wrapper = mount(CalendarPanel, { + propsData: { + value: new Date(2019, 9, 4), + partialUpdate: true, + }, + }); + wrapper + .findAll('.mx-table-year td > div') + .at(0) + .trigger('click'); + expect(wrapper.emitted().select[0][0]).toEqual(new Date(2010, 9, 4)); + wrapper.setProps({ value: new Date(2010, 9, 4) }); + wrapper + .findAll('.mx-table-month td > div') + .at(0) + .trigger('click'); + expect(wrapper.emitted().select[1][0]).toEqual(new Date(2010, 0, 4)); + }); }); diff --git a/__test__/calendar-range.test.js b/__test__/calendar-range.test.js index dbdb80f..f1f6ecf 100644 --- a/__test__/calendar-range.test.js +++ b/__test__/calendar-range.test.js @@ -63,4 +63,17 @@ describe('CalendarRange', () => { await flushPromises(); expect(wrapper.vm.calendars).toEqual([new Date(2019, 6, 1), new Date(2019, 7, 1)]); }); + + it('partialUpdate should be false', () => { + wrapper = mount(CalendarRange, { + propsData: { + partialUpdate: true, + }, + }); + const panels = wrapper.findAll(CalendarPanel); + const startPanel = panels.at(0); + const endPanel = panels.at(1); + expect(startPanel.vm.partialUpdate).toBe(false); + expect(endPanel.vm.partialUpdate).toBe(false); + }); }); diff --git a/__test__/datetime-panel.test.js b/__test__/datetime-panel.test.js index 1968b52..d49e580 100644 --- a/__test__/datetime-panel.test.js +++ b/__test__/datetime-panel.test.js @@ -11,6 +11,7 @@ describe('DatetimePanel', () => { it('feat: click date', () => { wrapper = mount(DatetimePanel, { propsData: { + type: 'datetime', defaultValue: new Date(2019, 9, 1, 12), }, }); diff --git a/__test__/datetime-range.test.js b/__test__/datetime-range.test.js index 7d81cee..ec8258a 100644 --- a/__test__/datetime-range.test.js +++ b/__test__/datetime-range.test.js @@ -13,6 +13,7 @@ describe('DatetimeRange', () => { wrapper = mount(DatetimeRange, { sync: false, propsData: { + type: 'datetime', value: [new Date(2019, 9, 4, 18), new Date(2019, 9, 6, 12)], }, }); diff --git a/src/calendar/calendar-panel.vue b/src/calendar/calendar-panel.vue index a5ab811..361ba7e 100644 --- a/src/calendar/calendar-panel.vue +++ b/src/calendar/calendar-panel.vue @@ -146,6 +146,11 @@ export default { default: 'YYYY-MM-DD', }, calendar: Date, + // update date when select year or month + partialUpdate: { + type: Boolean, + default: false, + }, }, data() { const panels = ['date', 'year', 'month']; @@ -252,6 +257,10 @@ export default { const nextCalendar = setYear(this.innerCalendar, year); this.updateCalendar(nextCalendar); this.handelPanelChange('month'); + if (this.partialUpdate && this.innerValue[0]) { + const date = setYear(this.innerValue[0], year); + this.emitDate(date, 'year'); + } } }, handleSelectMonth(month) { @@ -262,6 +271,10 @@ export default { const nextCalendar = setMonth(this.innerCalendar, month); this.updateCalendar(nextCalendar); this.handelPanelChange('date'); + if (this.partialUpdate && this.innerValue[0]) { + const date = setMonth(setYear(this.innerValue[0], this.calendarYear), month); + this.emitDate(date, 'month'); + } } }, handleSelectDate(day) { diff --git a/src/calendar/calendar-range.js b/src/calendar/calendar-range.js index 08585db..7f02d1d 100644 --- a/src/calendar/calendar-range.js +++ b/src/calendar/calendar-range.js @@ -3,6 +3,7 @@ import CalendarPanel from './calendar-panel'; import { getValidDate, isValidDate, isValidRangeDate } from '../util/date'; export default { + name: 'CalendarRange', components: { CalendarPanel }, props: { ...CalendarPanel.props, @@ -107,6 +108,8 @@ export default { calendar, value: this.innerValue, getClasses: this.getRangeClasses, + // don't update when range is true + partialUpdate: false, }; const on = { select: this.handleSelect, diff --git a/src/datetime/datetime-panel.js b/src/datetime/datetime-panel.js index 600099b..bc8680f 100644 --- a/src/datetime/datetime-panel.js +++ b/src/datetime/datetime-panel.js @@ -42,16 +42,14 @@ export default { handleSelect(date, type) { if (type === 'date') { this.openTimePanel(); - const time = isValidDate(this.value) ? this.value : new Date(this.defaultValue); - const datetime = new Date(date); - datetime.setHours(time.getHours(), time.getMinutes(), time.getSeconds()); - if (this.disabledTime(new Date(datetime))) { - this.currentValue = date; - } else { - this.emitDate(datetime, type); - } + } + const time = isValidDate(this.value) ? this.value : new Date(this.defaultValue); + const datetime = new Date(date); + datetime.setHours(time.getHours(), time.getMinutes(), time.getSeconds()); + if (this.disabledTime(new Date(datetime))) { + this.currentValue = date; } else { - this.emitDate(date, type); + this.emitDate(datetime, type); } }, }, @@ -59,6 +57,7 @@ export default { const calendarProps = { props: { ...pick(this, Object.keys(CalendarPanel.props)), + type: 'date', value: this.currentValue, }, on: { @@ -72,7 +71,7 @@ export default { value: this.currentValue, }, on: { - select: this.handleSelect, + select: this.emitDate, 'title-click': this.closeTimePanel, }, }; diff --git a/src/datetime/datetime-range.js b/src/datetime/datetime-range.js index aecc3e6..c1a41cd 100644 --- a/src/datetime/datetime-range.js +++ b/src/datetime/datetime-range.js @@ -42,22 +42,20 @@ export default { handleSelect(dates, type) { if (type === 'date') { this.openTimePanel(); - let datetimes = dates.map((v, i) => { - const datetime = new Date(v); - const time = isValidRangeDate(this.value) ? this.value[i] : new Date(this.defaultValue); - datetime.setHours(time.getHours(), time.getMinutes(), time.getSeconds()); - return datetime; - }); - if (datetimes[1].getTime() < datetimes[0].getTime()) { - datetimes = [datetimes[0], datetimes[0]]; - } - if (datetimes.some(this.disabledTime)) { - this.currentValue = dates; - } else { - this.emitDate(datetimes, type); - } + } + let datetimes = dates.map((v, i) => { + const datetime = new Date(v); + const time = isValidRangeDate(this.value) ? this.value[i] : new Date(this.defaultValue); + datetime.setHours(time.getHours(), time.getMinutes(), time.getSeconds()); + return datetime; + }); + if (datetimes[1].getTime() < datetimes[0].getTime()) { + datetimes = [datetimes[0], datetimes[0]]; + } + if (datetimes.some(this.disabledTime)) { + this.currentValue = dates; } else { - this.emitDate(dates, type); + this.emitDate(datetimes, type); } }, }, @@ -65,6 +63,7 @@ export default { const calendarProps = { props: { ...pick(this, Object.keys(CalendarRange.props)), + type: 'date', value: this.currentValue, }, on: { @@ -78,7 +77,7 @@ export default { showTimeHeader: true, }, on: { - select: this.handleSelect, + select: this.emitDate, 'title-click': this.closeTimePanel, }, };