Daan De Deckere
2018-02-12 d40f6d89bf9084e5d03df1aeea8bffd67662f0c0
Add onSubtractTime and onAddTime hooks (#508)

* Add onSubtractTime and onAddTime hooks

* Add tests for onSubtractTime and onAddTime hooks

* Fix mixup in describe blocks

* Give onSubtractTime and onAddTime hooks more logical names onNavigateBack and onNavigateForward
5 files modified
117 ■■■■ changed files
DateTime.d.ts 10 ●●●●● patch | view | raw | blame | history
DateTime.js 33 ●●●●● patch | view | raw | blame | history
README.md 2 ●●●●● patch | view | raw | blame | history
react-datetime.d.ts 14 ●●●● patch | view | raw | blame | history
test/tests.spec.js 58 ●●●●● patch | view | raw | blame | history
DateTime.d.ts
@@ -99,6 +99,16 @@
         */
        onViewModeChange?: (viewMode: string) => void;
        /*
         Callback trigger when the user navigates to the previous month, year or decade.
         The callback receives the amount and type ('month', 'year') as parameters.
         */
        onNavigateBack?: (amount: number, type: string) => void;
        /*
         Callback trigger when the user navigates to the next month, year or decade.
         The callback receives the amount and type ('month', 'year') as parameters.
         */
        onNavigateForward?: (amount: number, type: string) => void;
        /*
         The default view to display when the picker is shown. ('years', 'months', 'days', 'time')
         */
        viewMode?: ViewMode | number;
DateTime.js
@@ -26,6 +26,8 @@
        onBlur: TYPES.func,
        onChange: TYPES.func,
        onViewModeChange: TYPES.func,
        onNavigateBack: TYPES.func,
        onNavigateForward: TYPES.func,
        locale: TYPES.string,
        utc: TYPES.bool,
        input: TYPES.bool,
@@ -254,26 +256,29 @@
        };
    },
    addTime: function( amount, type, toSelected ) {
        return this.updateTime( 'add', amount, type, toSelected );
    subtractTime: function( amount, type, toSelected ) {
        var me = this;
        return function() {
            me.props.onNavigateBack( amount, type );
            me.updateTime( 'subtract', amount, type, toSelected );
        };
    },
    subtractTime: function( amount, type, toSelected ) {
        return this.updateTime( 'subtract', amount, type, toSelected );
    addTime: function( amount, type, toSelected ) {
        var me = this;
        return function() {
            me.props.onNavigateForward( amount, type );
            me.updateTime( 'add', amount, type, toSelected );
        };
    },
    updateTime: function( op, amount, type, toSelected ) {
        var me = this;
        var update = {},
            date = toSelected ? 'selectedDate' : 'viewDate';
        return function() {
            var update = {},
                date = toSelected ? 'selectedDate' : 'viewDate'
            ;
        update[ date ] = this.state[ date ].clone()[ op ]( amount, type );
            update[ date ] = me.state[ date ].clone()[ op ]( amount, type );
            me.setState( update );
        };
        this.setState( update );
    },
    allowedSetTime: ['hours', 'minutes', 'seconds', 'milliseconds'],
@@ -459,6 +464,8 @@
    onBlur: function() {},
    onChange: function() {},
    onViewModeChange: function() {},
    onNavigateBack: function() {},
    onNavigateForward: function() {},
    timeFormat: true,
    timeConstraints: {},
    dateFormat: true,
README.md
@@ -54,6 +54,8 @@
| **onFocus** | `function` | empty function | Callback trigger for when the user opens the datepicker. The callback receives an event of type SyntheticEvent. |
| **onBlur** | `function` | empty function | Callback trigger for when the user clicks outside of the input, simulating a regular onBlur. The callback receives the selected `moment` object as only parameter, if the date in the input is valid. If the date in the input is not valid, the callback returned. |
| **onViewModeChange** | `function` | empty function | Callback trigger when the view mode changes. The callback receives the selected view mode string (`years`, `months`, `days` or `time`) as only parameter.|
| **onNavigateBack** | `function` | empty function | Callback trigger when the user navigates to the previous month, year or decade. The callback receives the amount and type ('month', 'year') as parameters. |
| **onNavigateForward** | `function` | empty function | Callback trigger when the user navigates to the next month, year or decade. The callback receives the amount and type ('month', 'year') as parameters. |
| **viewMode** | `string` or `number` | `'days'` | The default view to display when the picker is shown (`'years'`, `'months'`, `'days'`, `'time'`). |
| **className** | `string` or `string array` | `''` | Extra class name for the outermost markup element. |
| **inputProps** | `object` | `undefined` | Defines additional attributes for the input element of the component. For example: `onClick`, `placeholder`, `disabled`, `required`, `name` and `className` (`className` *sets* the class attribute for the input element). See [Customize the Input Appearance](#customize-the-input-appearance). |
react-datetime.d.ts
@@ -80,6 +80,16 @@
    */
    onViewModeChange?: (viewMode: string) => void;
    /*
      Callback trigger when the user navigates to the previous month, year or decade.
      The callback receives the amount and type ('month', 'year') as parameters.
     */
    onNavigateBack?: (amount: number, type: string) => void;
    /*
      Callback trigger when the user navigates to the next month, year or decade.
      The callback receives the amount and type ('month', 'year') as parameters.
     */
    onNavigateForward?: (amount: number, type: string) => void;
    /*
     The default view to display when the picker is shown. ('years', 'months', 'days', 'time')
     */
    viewMode?: string|number;
@@ -92,8 +102,8 @@
     */
    inputProps?: Object;
    /*
     Replace the rendering of the input element. The accepted function has openCalendar
     (a function which opens the calendar) and the default calculated props for the input.
     Replace the rendering of the input element. The accepted function has openCalendar
     (a function which opens the calendar) and the default calculated props for the input.
     Must return a React component or null.
     */
    renderInput?: (props: Object, openCalendar: Function) => React.Component<any, any>;
test/tests.spec.js
@@ -1087,6 +1087,64 @@
    });
    describe('onNavigateForward', () => {
        it('when moving to next month', () => {
            const component = utils.createDatetime({ onNavigateForward: (amount, type) => {
                expect(amount).toEqual(1);
                expect(type).toEqual('months');
            }});
            utils.clickOnElement(component.find('.rdtNext'));
        });
        it('when moving to next year', () => {
            const component = utils.createDatetime({ viewMode: 'months', onNavigateForward: (amount, type) => {
                expect(amount).toEqual(1);
                expect(type).toEqual('years');
            }});
            utils.clickOnElement(component.find('.rdtNext'));
        });
        it('when moving decade forward', () => {
            const component = utils.createDatetime({ viewMode: 'years', onNavigateForward: (amount, type) => {
                expect(amount).toEqual(10);
                expect(type).toEqual('years');
            }});
            utils.clickOnElement(component.find('.rdtNext'));
        });
    });
    describe('onNavigateBack', () => {
        it('when moving to previous month', () => {
            const component = utils.createDatetime({ onNavigateBack: (amount, type) => {
                expect(amount).toEqual(1);
                expect(type).toEqual('months');
            }});
            utils.clickOnElement(component.find('.rdtPrev'));
        });
        it('when moving to previous year', () => {
            const component = utils.createDatetime({ viewMode: 'months', onNavigateBack: (amount, type) => {
                expect(amount).toEqual(1);
                expect(type).toEqual('years');
            }});
            utils.clickOnElement(component.find('.rdtPrev'));
        });
        it('when moving decade back', () => {
            const component = utils.createDatetime({ viewMode: 'years', onNavigateBack: (amount, type) => {
                expect(amount).toEqual(10);
                expect(type).toEqual('years');
            }});
            utils.clickOnElement(component.find('.rdtPrev'));
        });
    });
    describe('with set value', () => {
        it('date value', () => {
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),