Skip to content

Commit de12087

Browse files
forum-ismartijnrusschen
authored andcommitted
New functionality to adjust day when changing week, month or year (Hacker0x01#1123)
* Change date on month switch and year select * Change date on month switch and year select Prop 'adjustDateOnChange' offers a possibility to update the date respectively on month switch or year select. Keyboard support. * Error corrections. * Added tests for 'adjustDateOnChange' * Bugfix
1 parent fb787d0 commit de12087

File tree

4 files changed

+91
-4
lines changed

4 files changed

+91
-4
lines changed

src/calendar.jsx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ const isDropdownSelect = (element = {}) => {
4444

4545
export default class Calendar extends React.Component {
4646
static propTypes = {
47+
adjustDateOnChange: PropTypes.bool,
4748
className: PropTypes.string,
4849
children: PropTypes.node,
4950
dateFormat: PropTypes.oneOfType([
@@ -93,7 +94,8 @@ export default class Calendar extends React.Component {
9394
withPortal: PropTypes.bool,
9495
utcOffset: PropTypes.number,
9596
weekLabel: PropTypes.string,
96-
yearDropdownItemNumber: PropTypes.number
97+
yearDropdownItemNumber: PropTypes.number,
98+
setOpen: PropTypes.func
9799
}
98100

99101
static get defaultProps () {
@@ -189,6 +191,14 @@ export default class Calendar extends React.Component {
189191
if (this.props.onMonthChange) {
190192
this.props.onMonthChange(date)
191193
}
194+
if (this.props.adjustDateOnChange) {
195+
if (this.props.onSelect) {
196+
this.props.onSelect(date)
197+
}
198+
if (this.props.setOpen) {
199+
this.props.setOpen(true)
200+
}
201+
}
192202
}
193203

194204
changeYear = (year) => {
@@ -276,6 +286,10 @@ export default class Calendar extends React.Component {
276286
}
277287
return (
278288
<YearDropdown
289+
adjustDateOnChange={this.props.adjustDateOnChange}
290+
date={this.state.date}
291+
onSelect={this.props.onSelect}
292+
setOpen={this.props.setOpen}
279293
dropdownMode={this.props.dropdownMode}
280294
onChange={this.changeYear}
281295
minDate={this.props.minDate}

src/index.jsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ const WrappedCalendar = onClickOutside(Calendar)
4444

4545
export default class DatePicker extends React.Component {
4646
static propTypes = {
47+
adjustDateOnChange: PropTypes.bool,
4748
allowSameDay: PropTypes.bool,
4849
autoComplete: PropTypes.string,
4950
autoFocus: PropTypes.bool,
@@ -397,6 +398,9 @@ export default class DatePicker extends React.Component {
397398
newSelection = addYears(copy, 1)
398399
break
399400
}
401+
if (this.props.adjustDateOnChange) {
402+
this.setSelected(newSelection)
403+
}
400404
this.setPreSelection(newSelection)
401405
}
402406
}
@@ -414,6 +418,8 @@ export default class DatePicker extends React.Component {
414418
return <WrappedCalendar
415419
ref={(elem) => { this.calendar = elem }}
416420
locale={this.props.locale}
421+
adjustDateOnChange={this.props.adjustDateOnChange}
422+
setOpen={this.setOpen}
417423
dateFormat={this.props.dateFormatCalendar}
418424
useWeekdaysShort={this.props.useWeekdaysShort}
419425
dropdownMode={this.props.dropdownMode}

src/year_dropdown.jsx

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,17 @@ var WrappedYearDropdownOptions = onClickOutside(YearDropdownOptions)
88

99
export default class YearDropdown extends React.Component {
1010
static propTypes = {
11+
adjustDateOnChange: PropTypes.bool,
1112
dropdownMode: PropTypes.oneOf(['scroll', 'select']).isRequired,
1213
maxDate: PropTypes.object,
1314
minDate: PropTypes.object,
1415
onChange: PropTypes.func.isRequired,
1516
scrollableYearDropdown: PropTypes.bool,
1617
year: PropTypes.number.isRequired,
17-
yearDropdownItemNumber: PropTypes.number
18+
yearDropdownItemNumber: PropTypes.number,
19+
date: PropTypes.object,
20+
onSelect: PropTypes.func,
21+
setOpen: PropTypes.func
1822
}
1923

2024
state = {
@@ -46,7 +50,7 @@ export default class YearDropdown extends React.Component {
4650
)
4751

4852
renderReadView = (visible) => (
49-
<div key="read" style={{visibility: visible ? 'visible' : 'hidden'}} className="react-datepicker__year-read-view" onClick={this.toggleDropdown}>
53+
<div key="read" style={{visibility: visible ? 'visible' : 'hidden'}} className="react-datepicker__year-read-view" onClick={(event) => this.toggleDropdown(event)}>
5054
<span className="react-datepicker__year-read-view--down-arrow" />
5155
<span className="react-datepicker__year-read-view--selected-year">{this.props.year}</span>
5256
</div>
@@ -80,12 +84,33 @@ export default class YearDropdown extends React.Component {
8084
this.props.onChange(year)
8185
}
8286

83-
toggleDropdown = () => {
87+
toggleDropdown = (event) => {
8488
this.setState({
8589
dropdownVisible: !this.state.dropdownVisible
90+
}, () => {
91+
if (this.props.adjustDateOnChange) {
92+
this.handleYearChange(this.props.date, event)
93+
}
8694
})
8795
}
8896

97+
handleYearChange = (date, event) => {
98+
this.onSelect(date, event)
99+
this.setOpen()
100+
}
101+
102+
onSelect = (date, event) => {
103+
if (this.props.onSelect) {
104+
this.props.onSelect(date, event)
105+
}
106+
}
107+
108+
setOpen = () => {
109+
if (this.props.setOpen) {
110+
this.props.setOpen(true)
111+
}
112+
}
113+
89114
render () {
90115
let renderedDropdown
91116
switch (this.props.dropdownMode) {

test/calendar_test.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ import React from 'react'
22
import Calendar from '../src/calendar'
33
import Month from '../src/month'
44
import Day from '../src/day'
5+
import ReactDOM from 'react-dom'
6+
import TestUtils from 'react-dom/test-utils'
57
import YearDropdown from '../src/year_dropdown'
68
import MonthDropdown from '../src/month_dropdown'
9+
import DatePicker from '../src/index.jsx'
710
import { shallow, mount } from 'enzyme'
811
import sinon from 'sinon'
912
import * as utils from '../src/date_utils'
@@ -252,6 +255,45 @@ describe('Calendar', function () {
252255
expect(daysNamesMin.at(6).text()).to.equal('GG')
253256
})
254257

258+
it('should set the date to the selected day of the previous month when previous button clicked', () => {
259+
let date
260+
const expectedDate = '28.06.2017'
261+
const datePicker = TestUtils.renderIntoDocument(
262+
<DatePicker selected={utils.newDate('2017-07-28')} adjustDateOnChange onChange={(d) => { date = d }}/>
263+
)
264+
TestUtils.Simulate.focus(ReactDOM.findDOMNode(datePicker.input))
265+
const calendar = TestUtils.scryRenderedComponentsWithType(datePicker.calendar, Calendar)[0]
266+
const previousButton = TestUtils.findRenderedDOMComponentWithClass(calendar, 'react-datepicker__navigation--previous')
267+
TestUtils.Simulate.click(previousButton)
268+
expect(utils.formatDate(date, 'DD.MM.YYYY')).to.equal(expectedDate)
269+
})
270+
271+
it('should set the date to the selected day of the next when next button clicked', () => {
272+
let date
273+
const expectedDate = '28.08.2017'
274+
const datePicker = TestUtils.renderIntoDocument(
275+
<DatePicker selected={utils.newDate('2017-07-28')} adjustDateOnChange onChange={(d) => { date = d }}/>
276+
)
277+
TestUtils.Simulate.focus(ReactDOM.findDOMNode(datePicker.input))
278+
const calendar = TestUtils.scryRenderedComponentsWithType(datePicker.calendar, Calendar)[0]
279+
const nextButton = TestUtils.findRenderedDOMComponentWithClass(calendar, 'react-datepicker__navigation--next')
280+
TestUtils.Simulate.click(nextButton)
281+
expect(utils.formatDate(date, 'DD.MM.YYYY')).to.equal(expectedDate)
282+
})
283+
284+
it('should set the date to the last possible day of the previous month when previous button clicked', () => {
285+
let date
286+
const expectedDate = '30.11.2017'
287+
const datePicker = TestUtils.renderIntoDocument(
288+
<DatePicker selected={utils.newDate('2017-12-31')} adjustDateOnChange onChange={(d) => { date = d }}/>
289+
)
290+
TestUtils.Simulate.focus(ReactDOM.findDOMNode(datePicker.input))
291+
const calendar = TestUtils.scryRenderedComponentsWithType(datePicker.calendar, Calendar)[0]
292+
const previousButton = TestUtils.findRenderedDOMComponentWithClass(calendar, 'react-datepicker__navigation--previous')
293+
TestUtils.Simulate.click(previousButton)
294+
expect(utils.formatDate(date, 'DD.MM.YYYY')).to.equal(expectedDate)
295+
})
296+
255297
describe('onMonthChange', () => {
256298
let onMonthChangeSpy = sinon.spy()
257299
let calendar

0 commit comments

Comments
 (0)