Skip to content

Commit 45e15ac

Browse files
authored
adding option to disable unselect (#326)
* adding option to disable unselect * trying to fix e2e * trying to fix e2e * trying to fix e2e * trying to fix e2e
1 parent 2afab78 commit 45e15ac

15 files changed

+218
-14
lines changed

README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@ Here are the available configurations:
117117
| timeSeparator | `String` | `":"` | `daytime\|time` | The separator that will be placed between hours and minutes and between minutes and seconds on the time select. |
118118
| showMultipleYearsNavigation | `boolean` | `false` | `day\|month\|daytime` | If set to `true` will show buttons to navigate by multiple years (10 by default) |
119119
| multipleYearsNavigateBy | `number` | `10` | `day\|month\|daytime` | Number of years to navigate when showMultipleYearsNavigation is `true` |
120-
| returnedValueType | `ECalendarValue` | will try to guess by provided input type, fallbacks to `Moment` | All | The returned value type (`Moment`, `Moment[]`, `string`, `string[]` |
120+
| returnedValueType | `ECalendarValue` | `Moment` | All | The returned value type (`Moment`, `Moment[]`, `string`, `string[]` |
121+
| unSelectOnClick | `boolean` | true | `day\|month` | Will allow disallow/unselect to selected date by clicking on the selected date |
121122

122123
### API:
123124
In order to use the date-picker api user the `@ViewChild` annotation in the date-picker containing component class, take at the example below:

e2e/app.po.ts

+18-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {$, $$, browser, by, element} from 'protractor';
22

33
export class DemoPage {
44
private popupSelector = '.dp-popup.dp-main';
5-
body = $('body');
5+
emptyElem = $('.dp-place-holder');
66
dayPickerInput = $('#datePicker input');
77
timePickerInput = $('#timePicker input');
88
daytimePickerInput = $('#daytimePicker input');
@@ -19,6 +19,8 @@ export class DemoPage {
1919
monthWeeks = $$(`${this.popupSelector} .dp-calendar-week`);
2020
calendarDays = $$(`${this.popupSelector} .dp-calendar-day`);
2121
selectedDays = $$(`${this.popupSelector} .dp-calendar-day.dp-selected`);
22+
selectedDay = $(`.dp-calendar-day.dp-selected`);
23+
selectedMonth = $(`.dp-calendar-month.dp-selected`);
2224
dayCalendarLeftNavBtn = $(`${this.popupSelector} .dp-calendar-nav-left`);
2325
dayCalendarLeftSecondaryNavBtn = $(`${this.popupSelector} .dp-calendar-secondary-nav-left`);
2426
dayCalendarRightNavBtn = $(`${this.popupSelector} .dp-calendar-nav-right`);
@@ -56,6 +58,8 @@ export class DemoPage {
5658
localeOptions = $('#locale');
5759
hideGoToCurrentRadio = $('#hideGoToCurrent');
5860
showGoToCurrentRadio = $('#showGoToCurrent');
61+
enableUnselectSelected = $('#enableUnSelect');
62+
disableUnselectSelected = $('#disableUnSelect');
5963
pickerEnabledRadio = $('#inputEnabledRadio');
6064
pickerDisabledRadio = $('#inputDisabledRadio');
6165
enableRequiredValidationRadio = $('#enableRequiredRadio');
@@ -147,8 +151,7 @@ export class DemoPage {
147151
}
148152

149153
clickOnBody() {
150-
this.body.click();
151-
this.body.click();
154+
this.emptyElem.click();
152155
}
153156

154157
scrollIntoView(el, top = false) {
@@ -158,4 +161,16 @@ export class DemoPage {
158161
clickOnDayButton(text: string) {
159162
element(by.cssContainingText(`${this.popupSelector} .dp-calendar-day`, text)).click();
160163
}
164+
165+
clickOnDayButtonInline(text: string) {
166+
element(by.cssContainingText(`.dp-inline-day .dp-calendar-day`, text)).click();
167+
}
168+
169+
clickOnMonthButton(text: string) {
170+
element(by.cssContainingText(`${this.popupSelector} .dp-calendar-month`, text)).click();
171+
}
172+
173+
clickOnMonthButtonInline(text: string) {
174+
element(by.cssContainingText(`.dp-inline-month .dp-calendar-month`, text)).click();
175+
}
161176
}

e2e/datpicker-e2e.spec.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -85,22 +85,22 @@ describe('dpDayPicker dayPicker', () => {
8585
});
8686

8787
it('should disable/enable month selection', () => {
88-
page.dayPickerInput.sendKeys('08-04-2017');
88+
page.dayPickerInput.sendKeys('08-04-2018');
8989
page.dayPickerInput.click();
9090
expect(page.dayCalendarNavHeaderBtn.isPresent()).toBe(true);
9191
expect(page.dayCalendarContainer.isDisplayed()).toBe(true);
92-
expect(page.dayCalendarNavHeaderBtn.getText()).toEqual('Apr, 2017');
92+
expect(page.dayCalendarNavHeaderBtn.getText()).toEqual('Apr, 2018');
9393

9494
page.dayCalendarNavHeaderBtn.click();
9595
expect(page.dayCalendarContainer.isPresent()).toBe(false);
9696
expect(page.monthCalendar.isPresent()).toBe(true);
97-
expect(page.dayCalendarNavMonthHeaderBtn.getText()).toEqual('2017');
97+
expect(page.dayCalendarNavMonthHeaderBtn.getText()).toEqual('2018');
9898
expect(page.currentMonthCalendarBtn.getText()).toEqual(moment().format('MMM'));
9999
page.monthCalendarLeftNavBtn.click();
100-
expect(page.dayCalendarNavMonthHeaderBtn.getText()).toEqual('2016');
100+
expect(page.dayCalendarNavMonthHeaderBtn.getText()).toEqual('2017');
101101
expect(page.currentMonthCalendarBtn.isPresent()).toBe(false);
102102
page.monthCalendarRightNavBtn.click();
103-
expect(page.dayCalendarNavMonthHeaderBtn.getText()).toEqual('2017');
103+
expect(page.dayCalendarNavMonthHeaderBtn.getText()).toEqual('2018');
104104
expect(page.currentMonthCalendarBtn.getText()).toEqual(moment().format('MMM'));
105105

106106
page.clickOnBody();

e2e/selected-unselect-e2e.spec.ts

+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
import {DemoPage} from './app.po';
2+
import * as moment from 'moment';
3+
import {browser} from 'protractor';
4+
import * as fs from 'fs';
5+
import {TestUtils} from './test-utils';
6+
7+
describe('dpDayPicker timePicker', () => {
8+
9+
let page: DemoPage;
10+
11+
beforeEach(() => {
12+
page = new DemoPage();
13+
page.navigateTo();
14+
});
15+
16+
it('should make sure unSelectOnClick feature works as expected for day calendar', () => {
17+
const dayRunner = (menuItem, input, isPicker) => {
18+
const date = moment();
19+
const dayClick = () => {
20+
if (isPicker) {
21+
page.clickOnDayButton(date.format('DD'));
22+
} else {
23+
page.clickOnDayButtonInline(date.format('DD'));
24+
}
25+
};
26+
27+
menuItem.click();
28+
page.enableUnselectSelected.click();
29+
30+
if (isPicker) {
31+
page.scrollIntoView(page.noCloseOnSelect);
32+
page.noCloseOnSelect.click();
33+
input.click();
34+
}
35+
36+
dayClick();
37+
expect(page.selectedDay.isPresent()).toEqual(true);
38+
dayClick();
39+
expect(page.selectedDay.isPresent()).toEqual(false);
40+
41+
page.clickOnBody();
42+
43+
page.disableUnselectSelected.click();
44+
45+
if (isPicker) {
46+
input.click();
47+
}
48+
49+
dayClick();
50+
51+
expect(page.selectedDay.isPresent()).toEqual(true);
52+
53+
dayClick();
54+
expect(page.selectedDay.isPresent()).toEqual(true);
55+
56+
page.enableUnselectSelected.click();
57+
58+
if (isPicker) {
59+
input.click();
60+
}
61+
62+
dayClick();
63+
expect(page.selectedDay.isPresent()).toEqual(false);
64+
};
65+
66+
dayRunner(page.dayPickerMenu, page.dayPickerInput, true);
67+
dayRunner(page.dayDirectiveMenu, page.dayDirectiveInput, true);
68+
dayRunner(page.dayInlineMenu, null, false);
69+
});
70+
71+
it('should make sure unSelectOnClick feature works as expected for month calendar', () => {
72+
const monthRunner = (menuItem, input, isPicker) => {
73+
const date = moment();
74+
const dayClick = () => {
75+
if (isPicker) {
76+
page.clickOnMonthButton(date.format('MMM'));
77+
} else {
78+
page.clickOnMonthButtonInline(date.format('MMM'));
79+
}
80+
};
81+
82+
menuItem.click();
83+
page.enableUnselectSelected.click();
84+
85+
if (isPicker) {
86+
page.scrollIntoView(page.noCloseOnSelect);
87+
page.noCloseOnSelect.click();
88+
input.click();
89+
}
90+
91+
dayClick();
92+
expect(page.selectedMonth.isPresent()).toEqual(true);
93+
dayClick();
94+
expect(page.selectedMonth.isPresent()).toEqual(false);
95+
96+
page.clickOnBody();
97+
page.scrollIntoView(page.disableUnselectSelected);
98+
page.disableUnselectSelected.click();
99+
100+
if (isPicker) {
101+
input.click();
102+
}
103+
104+
dayClick();
105+
106+
expect(page.selectedMonth.isPresent()).toEqual(true);
107+
108+
dayClick();
109+
expect(page.selectedMonth.isPresent()).toEqual(true);
110+
111+
page.enableUnselectSelected.click();
112+
113+
if (isPicker) {
114+
input.click();
115+
}
116+
117+
dayClick();
118+
expect(page.selectedMonth.isPresent()).toEqual(false);
119+
};
120+
121+
monthRunner(page.monthPickerMenu, page.monthPickerInput, true);
122+
monthRunner(page.monthDirectiveMenu, page.monthDirectiveInput, true);
123+
monthRunner(page.monthInlineMenu, null, false);
124+
});
125+
});

e2e/test-utils.ts

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import * as fs from 'fs';
2+
import {browser} from 'protractor';
3+
4+
5+
export class TestUtils {
6+
static async takeScreenshot(filename) {
7+
const png = await browser.takeScreenshot();
8+
TestUtils.writeScreenShot(png, 'screens/' + filename + '.png');
9+
}
10+
11+
private static writeScreenShot(data: string, filename: string) {
12+
const stream = fs.createWriteStream(filename);
13+
stream.write(new Buffer(data, 'base64'));
14+
stream.end();
15+
}
16+
}

src/app/date-picker/date-picker.service.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ export class DatePickerService {
7777
showMultipleYearsNavigation: pickerConfig.showMultipleYearsNavigation,
7878
locale: pickerConfig.locale,
7979
returnedValueType: pickerConfig.returnedValueType,
80-
showGoToCurrent: pickerConfig.showGoToCurrent
80+
showGoToCurrent: pickerConfig.showGoToCurrent,
81+
unSelectOnClick: pickerConfig.unSelectOnClick
8182
};
8283
}
8384

src/app/day-calendar/day-calendar-config.model.ts

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export interface IConfig {
2828
showMultipleYearsNavigation?: boolean;
2929
returnedValueType?: ECalendarValue;
3030
showGoToCurrent?: boolean;
31+
unSelectOnClick?: boolean;
3132
}
3233

3334
export interface IDayCalendarConfig extends IConfig,

src/app/day-calendar/day-calendar.component.ts

+4
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,10 @@ export class DayCalendarComponent implements OnInit, OnChanges, ControlValueAcce
210210
}
211211

212212
dayClicked(day: IDay) {
213+
if (day.selected && !this.componentConfig.unSelectOnClick) {
214+
return;
215+
}
216+
213217
this.selected = this.utilsService
214218
.updateSelected(this.componentConfig.allowMultiSelect, this.selected, day);
215219
this.weeks = this.dayCalendarService

src/app/day-calendar/day-calendar.service.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ export class DayCalendarService {
2020
monthFormat: 'MMM, YYYY',
2121
enableMonthSelector: true,
2222
locale: moment.locale(),
23-
dayBtnFormat: 'DD'
23+
dayBtnFormat: 'DD',
24+
unSelectOnClick: true
2425
};
2526

2627
constructor(private utilsService: UtilsService) {

src/app/demo/demo/demo.component.html

+25
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ <h3 class="dp-menu-header">Components</h3>
5555
[ngClass]="{'dp-active-item': pickerMode == 'timeDirective'}">Time Picker directive</a>
5656
</li>
5757
</ul>
58+
<div class="dp-place-holder"></div>
5859
</div>
5960

6061
<div *ngIf="showDemo" class="dp-demo-container" [ngClass]="{'dp-not-top': !isAtTop,
@@ -1032,6 +1033,30 @@ <h3 class="dp-options-section">Config options</h3>
10321033
</div>
10331034
</div>
10341035

1036+
<div class="dp-option" *ngIf="isValidConfig('unSelectOnClick')">
1037+
<span class="dp-option-header">
1038+
Allow un select selected date (unSelectOnClick):
1039+
</span>
1040+
<div class="dp-option-playground">
1041+
<label>Enabled
1042+
<input id="enableUnSelect"
1043+
type="radio"
1044+
[(ngModel)]="config.unSelectOnClick"
1045+
name="unSelectOnClick"
1046+
[value]="true"
1047+
(ngModelChange)="configChanged('unSelectOnClick', 'true')">
1048+
</label>
1049+
<label>Disabled
1050+
<input id="disableUnSelect"
1051+
type="radio"
1052+
[(ngModel)]="config.unSelectOnClick"
1053+
name="unSelectOnClick"
1054+
[value]="false"
1055+
(ngModelChange)="configChanged('showGoToCurrent', 'false')">
1056+
</label>
1057+
</div>
1058+
</div>
1059+
10351060
<div class="dp-option" *ngIf="isValidConfig('dayBtnFormat')">
10361061
<span class="dp-option-header">
10371062
Day Button Format (dayBtnFormat):

src/app/demo/demo/demo.component.less

+5
Original file line numberDiff line numberDiff line change
@@ -148,4 +148,9 @@
148148
margin-top: @stickyHeightInlineDayTime;
149149
}
150150
}
151+
152+
.dp-place-holder {
153+
width: 1px;
154+
height: 1px;
155+
}
151156
}

src/app/demo/demo/demo.component.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ const MONTH_CALENDAR_OPTION_KEYS = [
5959
'showMultipleYearsNavigation',
6060
'yearFormat',
6161
'showGoToCurrent',
62+
'unSelectOnClick',
6263
...GLOBAL_OPTION_KEYS
6364
];
6465
const DAY_CALENDAR_OPTION_KEYS = [
@@ -75,6 +76,7 @@ const DAY_CALENDAR_OPTION_KEYS = [
7576
'dayBtnFormat',
7677
'weekdayFormat',
7778
'showGoToCurrent',
79+
'unSelectOnClick',
7880
...MONTH_CALENDAR_OPTION_KEYS
7981
];
8082
const TIME_SELECT_SHARED_OPTION_KEYS = [
@@ -212,7 +214,8 @@ export class DemoComponent {
212214
showMultipleYearsNavigation: false,
213215
locale: moment.locale(),
214216
hideInputContainer: false,
215-
returnedValueType: ECalendarValue.String
217+
returnedValueType: ECalendarValue.String,
218+
unSelectOnClick: true
216219
};
217220
isAtTop: boolean = true;
218221

src/app/month-calendar/month-calendar-config.ts

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export interface IConfig {
1616
showMultipleYearsNavigation?: boolean;
1717
returnedValueType?: ECalendarValue;
1818
showGoToCurrent?: boolean;
19+
unSelectOnClick?: boolean;
1920
}
2021

2122
export interface IMonthCalendarConfig extends IConfig,

src/app/month-calendar/month-calendar.component.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {ECalendarValue} from '../common/types/calendar-value-enum';
22
import {
3-
ChangeDetectionStrategy, ChangeDetectorRef,
3+
ChangeDetectionStrategy,
4+
ChangeDetectorRef,
45
Component,
56
EventEmitter,
67
forwardRef,
@@ -196,6 +197,10 @@ export class MonthCalendarComponent implements OnInit, OnChanges, ControlValueAc
196197
}
197198

198199
monthClicked(month: IMonth) {
200+
if (month.selected && !this.componentConfig.unSelectOnClick) {
201+
return;
202+
}
203+
199204
this.selected = this.utilsService
200205
.updateSelected(this.componentConfig.allowMultiSelect, this.selected, month, 'month');
201206
this.yearMonths = this.monthCalendarService

src/app/month-calendar/month-calendar.service.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ export class MonthCalendarService {
1515
monthBtnFormat: 'MMM',
1616
locale: moment.locale(),
1717
multipleYearsNavigateBy: 10,
18-
showMultipleYearsNavigation: false
18+
showMultipleYearsNavigation: false,
19+
unSelectOnClick: true
1920
};
2021

2122
constructor(private utilsService: UtilsService) {

0 commit comments

Comments
 (0)