Skip to content

Commit aad74ef

Browse files
author
Berger
committed
feat(datepicker): added customizable Button
added a button for customDates in DatePicker
1 parent fca45ba commit aad74ef

File tree

7 files changed

+112
-7
lines changed

7 files changed

+112
-7
lines changed

apps/ngx-bootstrap-docs/src/ng-api-doc.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,6 +1044,24 @@ export const ngdoc: any = {
10441044
"type": "string",
10451045
"description": "<p>CSS class which will be applied to datepicker container,\nusually used to set color theme</p>\n"
10461046
},
1047+
{
1048+
"name": "customButtonLabel",
1049+
"defaultValue": "Custom",
1050+
"type": "string",
1051+
"description": "<p>Label for &#39;custom&#39; button</p>\n"
1052+
},
1053+
{
1054+
"name": "customDateButton",
1055+
"defaultValue": "undefined",
1056+
"type": "Date",
1057+
"description": "<p>Shows button to select this Date</p>\n"
1058+
},
1059+
{
1060+
"name": "customPosition",
1061+
"defaultValue": "right",
1062+
"type": "string",
1063+
"description": "<p>Positioning of &#39;custom&#39; button</p>\n"
1064+
},
10471065
{
10481066
"name": "customRangeButtonLabel",
10491067
"defaultValue": "Custom Range",

src/datepicker/base/bs-datepicker-container.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ export abstract class BsDatepickerAbstractComponent {
2626
showClearBtn?: boolean;
2727
clearBtnLbl?: string;
2828
clearPos?: string;
29+
customDateBtn?: Date;
30+
customBtnLabel?: string;
31+
customBtnPos?: string;
32+
2933

3034
_effects?: BsDatepickerEffects;
3135
customRanges: BsCustomDates[] = [];
@@ -122,6 +126,9 @@ export abstract class BsDatepickerAbstractComponent {
122126
// eslint-disable-next-line
123127
clearDate(): void {}
124128

129+
// eslint-disable-next-line
130+
setCustomDate(): void {}
131+
125132
// eslint-disable-next-line @typescript-eslint/no-explicit-any
126133
_stopPropagation(event: any): void {
127134
event.stopPropagation();

src/datepicker/bs-datepicker.config.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,11 +149,19 @@ export class BsDatepickerConfig implements DatepickerRenderOptions {
149149
* Shows clear button
150150
*/
151151
showClearButton = false;
152+
/**
153+
* CustomDate clear button
154+
*/
155+
customDateButton?: Date = undefined;
152156

153157
/**
154158
* Positioning of 'today' button
155159
*/
156160
todayPosition = 'center';
161+
/**
162+
* Positioning of 'today' button
163+
*/
164+
customPosition = 'left';
157165

158166
/**
159167
* Positioning of 'clear' button
@@ -169,6 +177,10 @@ export class BsDatepickerConfig implements DatepickerRenderOptions {
169177
* Label for 'clear' button
170178
*/
171179
clearButtonLabel = 'Clear';
180+
/**
181+
* Label for custom Button
182+
*/
183+
customButtonLabel = 'Custom Date';
172184

173185
/**
174186
* Label for 'custom range' button

src/datepicker/bs-datepicker.scss

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,17 +472,23 @@
472472
}
473473

474474
.clear-right,
475+
.custom-right,
475476
.today-right {
476477
flex-grow: 0;
478+
order: 3
477479
}
478480
.clear-left,
481+
.custom-left,
479482
.today-left {
480483
flex-grow: 1;
484+
order: 1
481485
}
482486

483487
.clear-center,
488+
.custom-center,
484489
.today-center {
485490
flex-grow: 0.5;
491+
order: 2
486492
}
487493
}
488494
}

src/datepicker/testing/bs-datepicker.spec.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,22 @@ describe('datepicker:', () => {
178178
expect(buttonText.filter(button => button === clearBtnCustomLbl).length).toEqual(1);
179179
});
180180

181+
it('should show custom label for custom button if set in config', () => {
182+
const customBtnCustomLbl = 'Clear current';
183+
const datepickerDirective = getDatepickerDirective(fixture);
184+
datepickerDirective.bsConfig = {
185+
customButtonLabel: customBtnCustomLbl,
186+
customDateButton: new Date()
187+
};
188+
showDatepicker(fixture);
189+
190+
const buttonText: string[] = [];
191+
// fixture.debugElement.queryAll(By.css('button'))
192+
Array.from(document.body.getElementsByTagName('button'))
193+
.forEach(button => buttonText.push(button.textContent));
194+
expect(buttonText.filter(button => button === customBtnCustomLbl).length).toEqual(1);
195+
});
196+
181197
describe('should start with', () => {
182198

183199
const parameters = [
@@ -257,6 +273,37 @@ describe('datepicker:', () => {
257273
}).unsubscribe();
258274
});
259275

276+
it('should set custom date', () => {
277+
const datepicker = showDatepicker(fixture);
278+
const datepickerContainerInstance = getDatepickerContainer(datepicker);
279+
const customDate = new Date(2099, 11, 31)
280+
datepickerContainerInstance.customDateBtn = customDate;
281+
282+
datepickerContainerInstance[`_store`]
283+
.select(state => state.view)
284+
.subscribe(view => {
285+
view.date = new Date(2020, 0, 1);
286+
}).unsubscribe();
287+
fixture.detectChanges();
288+
289+
datepickerContainerInstance[`_store`]
290+
.select(state => state.view)
291+
.subscribe(view => {
292+
expect(`${(view.date.getDate())}-${(view.date.getMonth())}-${(view.date.getFullYear())}`)
293+
.not.toEqual(`${(customDate.getDate())}-${(customDate.getMonth())}-${(customDate.getFullYear())}`);
294+
}).unsubscribe();
295+
296+
datepickerContainerInstance.setCustomDate();
297+
fixture.detectChanges();
298+
299+
datepickerContainerInstance[`_store`]
300+
.select(state => state.view)
301+
.subscribe(view => {
302+
expect(`${(view.date.getDate())}-${(view.date.getMonth())}-${(view.date.getFullYear())}`)
303+
.toEqual(`${(customDate.getDate())}-${(customDate.getMonth())}-${(customDate.getFullYear())}`);
304+
}).unsubscribe();
305+
});
306+
260307
it('should clear date', () => {
261308
const datepicker = showDatepicker(fixture);
262309
const datepickerContainerInstance = getDatepickerContainer(datepicker);

src/datepicker/themes/bs/bs-datepicker-container.component.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ export class BsDatepickerContainerComponent extends BsDatepickerAbstractComponen
8080
this.showClearBtn = this._config.showClearButton;
8181
this.clearBtnLbl = this._config.clearButtonLabel;
8282
this.clearPos = this._config.clearPosition;
83+
this.customDateBtn = this._config.customDateButton;
84+
this.customBtnLabel = this._config.customButtonLabel;
85+
this.customBtnPos = this._config.customPosition;
8386
this.customRangeBtnLbl = this._config.customRangeButtonLabel;
8487
this._effects?.init(this._store)
8588
// intial state options
@@ -164,6 +167,10 @@ export class BsDatepickerContainerComponent extends BsDatepickerAbstractComponen
164167
this._store.dispatch(this._actions.select(undefined));
165168
}
166169

170+
setCustomDate(): void {
171+
this._store.dispatch(this._actions.select(this.customDateBtn == null ? undefined : new Date(this.customDateBtn)));
172+
}
173+
167174
ngOnDestroy(): void {
168175
for (const sub of this._subs) {
169176
sub.unsubscribe();

src/datepicker/themes/bs/bs-datepicker-view.html

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,14 @@
5454
</div>
5555

5656
<div class="bs-datepicker-buttons" *ngIf="showTodayBtn || showClearBtn">
57+
<div class="btn-custom-wrapper"
58+
[class.custom-left]="customBtnPos === 'left'"
59+
[class.custom-right]="customBtnPos === 'right'"
60+
[class.custom-center]="customBtnPos === 'center'"
61+
*ngIf="customDateBtn != null">
62+
<button class="btn btn-success" (click)="setCustomDate()">{{customBtnLabel}}</button>
63+
</div>
64+
5765
<div class="btn-today-wrapper"
5866
[class.today-left]="todayPos === 'left'"
5967
[class.today-right]="todayPos === 'right'"
@@ -62,13 +70,13 @@
6270
<button class="btn btn-success" (click)="setToday()">{{todayBtnLbl}}</button>
6371
</div>
6472

65-
<div class="btn-clear-wrapper"
66-
[class.clear-left]="clearPos === 'left'"
67-
[class.clear-right]="clearPos === 'right'"
68-
[class.clear-center]="clearPos === 'center'"
69-
*ngIf="showClearBtn">
70-
<button class="btn btn-success" (click)="clearDate()">{{clearBtnLbl}}</button>
71-
</div>
73+
<div class="btn-clear-wrapper"
74+
[class.clear-left]="clearPos === 'left'"
75+
[class.clear-right]="clearPos === 'right'"
76+
[class.clear-center]="clearPos === 'center'"
77+
*ngIf="showClearBtn">
78+
<button class="btn btn-success" (click)="clearDate()">{{clearBtnLbl}}</button>
79+
</div>
7280
</div>
7381

7482
</div>

0 commit comments

Comments
 (0)