Skip to content

Commit

Permalink
feat(datepicker): add param to prevent change to next month after fir…
Browse files Browse the repository at this point in the history
…st date pick in right calendar (#6058)

* feat(datepicker): add param to prevent change to next month after first date pick in right calendar

* docs(datepicker): add preventChangeToNextMonth parameter example

* fix(datepicker): fix MonthViewOption type error, fix datepicker reducer tests
  • Loading branch information
vladimirstempel authored Apr 12, 2021
1 parent a37d845 commit 2c671b6
Show file tree
Hide file tree
Showing 11 changed files with 1,502 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import { DemoDateRangePickerDisplayOneMonth } from './demos/daterangepicker-disp
import { DemoDatepickerTodayButtonComponent } from './demos/today-button/today-button';
import { DemoDatepickerClearButtonComponent } from './demos/clear-button/clear-button';
import { DemoDatepickerStartViewComponent } from "./demos/start-view/start-view";
import { DemoDatepickerPreventChangeToNextMonthComponent } from './demos/prevent-change-to-next-month/prevent-change-to-next-month.component';

export const demoComponentContent: ContentSection[] = [
{
Expand Down Expand Up @@ -410,6 +411,14 @@ export const demoComponentContent: ContentSection[] = [
description: `<p>Quick select ranges can be added to Daterangepicker using <code>ranges</code></p>`,
outlet: DemoDatePickerQuickSelectRangesComponent
},
{
title: 'Prevent change to next month',
anchor: 'prevent-change-to-next-month',
component: require('!!raw-loader!./demos/prevent-change-to-next-month/prevent-change-to-next-month.component.ts'),
html: require('!!raw-loader!./demos/prevent-change-to-next-month/prevent-change-to-next-month.component.html'),
description: `<p>Pick some date from second month and it wont change to the next month</p>`,
outlet: DemoDatepickerPreventChangeToNextMonthComponent
},
{
title: 'Previous month in Daterangepicker',
anchor: 'daterangepicker-previous-month',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import { DemoDateRangePickerDisplayOneMonth } from './daterangepicker-display-on
import { DemoDatepickerTodayButtonComponent } from './today-button/today-button';
import { DemoDatepickerClearButtonComponent } from './clear-button/clear-button';
import { DemoDatepickerStartViewComponent } from "./start-view/start-view";
import { DemoDatepickerPreventChangeToNextMonthComponent } from './prevent-change-to-next-month/prevent-change-to-next-month.component';

export const DEMO_COMPONENTS = [
DatepickerDemoComponent,
Expand Down Expand Up @@ -84,6 +85,7 @@ export const DEMO_COMPONENTS = [
DemoDatepickerClearButtonComponent,
DemoDateRangePickerShowPreviousMonth,
DemoDateRangePickerMaxDateRangeComponent,
DemoDatepickerPreventChangeToNextMonthComponent,
DemoDatePickerQuickSelectRangesComponent,
DemoDatepickerStartViewComponent
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<div class="row">
<div class="col-xs-12 col-12 col-md-4 form-group">
<input type="text"
placeholder="Daterangepicker"
class="form-control"
bsDaterangepicker
[bsConfig]="{ preventChangeToNextMonth: true }">
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Component } from '@angular/core';

@Component({
selector: 'demo-prevent-change-to-next-month',
templateUrl: './prevent-change-to-next-month.component.html'
})
export class DemoDatepickerPreventChangeToNextMonthComponent {
maxDate = new Date();

constructor() {
this.maxDate.setDate(this.maxDate.getDate() + 7);
}
}
5 changes: 5 additions & 0 deletions apps/ngx-bootstrap-docs/src/ng-api-doc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1099,6 +1099,11 @@ export const ngdoc: any = {
"type": "BsDatepickerViewMode",
"description": "<p>Default mode for all date pickers</p>\n"
},
{
"name": "preventChangeToNextMonth",
"type": "boolean",
"description": "<p>Prevents change to next month after first date pick in right calendar (dateRangePicker only)</p>\n"
},
{
"name": "rangeInputFormat",
"defaultValue": "L",
Expand Down
5 changes: 5 additions & 0 deletions src/datepicker/bs-datepicker.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ export class BsDatepickerConfig implements DatepickerRenderOptions {
*/
showPreviousMonth?: boolean;

/**
* Prevents change to next month for right calendar in two calendars view (dateRangePicker only)
*/
preventChangeToNextMonth?: boolean;

/**
* Add class to current day
*/
Expand Down
22 changes: 20 additions & 2 deletions src/datepicker/reducer/bs-datepicker.reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { BsViewNavigationEvent, DatepickerFormatOptions, BsDatepickerViewMode }
import { getYearsCalendarInitialDate } from '../utils/bs-calendar-utils';


export function bsDatepickerReducer(state = initialDatepickerState,
export function bsDatepickerReducer(state: BsDatepickerState = initialDatepickerState,
action: Action): BsDatepickerState {
switch (action.type) {
case BsDatepickerActions.CALCULATE: {
Expand Down Expand Up @@ -202,7 +202,7 @@ function calculateReducer(state: BsDatepickerState): BsDatepickerState {
}

state.monthViewOptions.firstDayOfWeek = getLocale(state.locale).firstDayOfWeek();
const monthsModel = new Array(displayMonths);
let monthsModel = new Array(displayMonths);
for (let monthIndex = 0; monthIndex < displayMonths; monthIndex++) {
// todo: for unlinked calendars it will be harder
monthsModel[monthIndex] = calcDaysCalendar(
Expand All @@ -211,6 +211,24 @@ function calculateReducer(state: BsDatepickerState): BsDatepickerState {
);
viewDate = shiftDate(viewDate, { month: 1 });
}
// Check if parameter enabled and check if it's not months navigation event
if (state.preventChangeToNextMonth && state.flaggedMonths && state.hoveredDate) {
const viewMonth = calcDaysCalendar(state.view.date, state.monthViewOptions);
// Check if viewed right month same as in flaggedMonths state, then override months model with flaggedMonths
if (state.flaggedMonths.length && state.flaggedMonths[1].month.getMonth() === viewMonth.month.getMonth()) {
monthsModel = state.flaggedMonths
.map(item => {
if (state.monthViewOptions) {
return calcDaysCalendar(
item.month,
state.monthViewOptions
)
}
return null;
})
.filter(item => item !== null);
}
}

return Object.assign({}, state, { monthsModel });
}
Expand Down
1 change: 1 addition & 0 deletions src/datepicker/reducer/bs-datepicker.state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export class BsDatepickerState
flaggedMonths?: DaysCalendarViewModel[];
selectFromOtherMonth?: boolean;
showPreviousMonth?: boolean; // dateRangePicker only;
preventChangeToNextMonth?: boolean; // dateRangePicker only;
displayOneMonthRange?: boolean; // dateRangePicker only;

// months calendar
Expand Down
47 changes: 45 additions & 2 deletions src/datepicker/testing/bs-datepicker.reducer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { bsDatepickerReducer } from '../reducer/bs-datepicker.reducer';
import { BsDatepickerActions } from '../reducer/bs-datepicker.actions';
import { Action } from 'ngx-bootstrap/mini-ngrx';
import { initialDatepickerState } from '../reducer/bs-datepicker.state';
import { mockFlaggedMonths } from './flaggedMonthsMock';

describe('BsDatepickerReducer.', () => {
it('navigateTo : "month" view mode', () => {
Expand All @@ -22,12 +23,54 @@ describe('BsDatepickerReducer.', () => {
initialDatepickerState.view.date = new Date(2017, 11, 1);

const action: Action = {
type: BsDatepickerActions.NAVIGATE_TO,
payload: { unit: { year: 2017, month: 11, day: 1}, viewMode: 'day' }
type: BsDatepickerActions.NAVIGATE_TO,
payload: { unit: { year: 2017, month: 11, day: 1}, viewMode: 'day' }
};

const reducer = bsDatepickerReducer(state, action);
expect(reducer.view.mode).toEqual('month');
expect(reducer.selectedDate).toEqual(new Date(2017, 11, 1));
});

it('preventChangeToNextMonth : months shouldn\'t change', () => {
const state = Object.assign({}, initialDatepickerState, {
preventChangeToNextMonth: true,
displayMonths: 2,
hoveredDate: true,
flaggedMonths: mockFlaggedMonths
});

initialDatepickerState.view.mode = 'day';
initialDatepickerState.view.date = new Date('2021-04-14T12:36:16');

const action: Action = {
type: BsDatepickerActions.CALCULATE,
payload: {}
};

const reducer = bsDatepickerReducer(state, action);
expect(reducer.view.mode).toEqual('day');
expect(reducer.monthsModel.pop().month).toEqual(state.flaggedMonths[1].month);
});

it('preventChangeToNextMonth : months should change', () => {
const state = Object.assign({}, initialDatepickerState, {
preventChangeToNextMonth: false,
displayMonths: 2,
hoveredDate: true,
flaggedMonths: mockFlaggedMonths
});

initialDatepickerState.view.mode = 'day';
initialDatepickerState.view.date = new Date('2021-04-14T12:36:16');

const action: Action = {
type: BsDatepickerActions.CALCULATE,
payload: {}
};

const reducer = bsDatepickerReducer(state, action);
expect(reducer.view.mode).toEqual('day');
expect((reducer.monthsModel.pop().month.toISOString() === state.flaggedMonths[1].month.toISOString())).toBeFalsy();
});
});
3 changes: 0 additions & 3 deletions src/datepicker/testing/bs-daterangepicker.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { By } from '@angular/platform-browser';
import { BsCustomDates } from '../themes/bs/bs-custom-dates-view.component';
import { take } from 'rxjs/operators';
import { getYearsCalendarInitialDate } from '../utils/bs-calendar-utils';
import { initialYearShift } from '../engine/format-years-calendar';


@Component({
Expand Down
Loading

0 comments on commit 2c671b6

Please sign in to comment.