From a1d534cc62d8bd8aa7f6c22f5e4663e38be145de Mon Sep 17 00:00:00 2001 From: Berger Date: Mon, 2 Aug 2021 10:45:26 +0200 Subject: [PATCH] feat(datepicker): added customizable Button added a button for customDates in DatePicker --- apps/ngx-bootstrap-docs/src/ng-api-doc.ts | 18 +++++++ .../base/bs-datepicker-container.ts | 7 +++ src/datepicker/bs-datepicker.config.ts | 12 +++++ src/datepicker/bs-datepicker.scss | 6 +++ src/datepicker/testing/bs-datepicker.spec.ts | 47 +++++++++++++++++++ .../bs/bs-datepicker-container.component.ts | 7 +++ .../themes/bs/bs-datepicker-view.html | 22 ++++++--- 7 files changed, 112 insertions(+), 7 deletions(-) diff --git a/apps/ngx-bootstrap-docs/src/ng-api-doc.ts b/apps/ngx-bootstrap-docs/src/ng-api-doc.ts index a26587c87c..5422644ba0 100644 --- a/apps/ngx-bootstrap-docs/src/ng-api-doc.ts +++ b/apps/ngx-bootstrap-docs/src/ng-api-doc.ts @@ -1044,6 +1044,24 @@ export const ngdoc: any = { "type": "string", "description": "

CSS class which will be applied to datepicker container,\nusually used to set color theme

\n" }, + { + "name": "customButtonLabel", + "defaultValue": "Custom", + "type": "string", + "description": "

Label for 'custom' button

\n" + }, + { + "name": "customDateButton", + "defaultValue": "undefined", + "type": "Date", + "description": "

Shows button to select this Date

\n" + }, + { + "name": "customPosition", + "defaultValue": "right", + "type": "string", + "description": "

Positioning of 'custom' button

\n" + }, { "name": "customRangeButtonLabel", "defaultValue": "Custom Range", diff --git a/src/datepicker/base/bs-datepicker-container.ts b/src/datepicker/base/bs-datepicker-container.ts index ba4efd24e5..49518f319c 100644 --- a/src/datepicker/base/bs-datepicker-container.ts +++ b/src/datepicker/base/bs-datepicker-container.ts @@ -26,6 +26,10 @@ export abstract class BsDatepickerAbstractComponent { showClearBtn?: boolean; clearBtnLbl?: string; clearPos?: string; + customDateBtn?: Date; + customBtnLabel?: string; + customBtnPos?: string; + _effects?: BsDatepickerEffects; customRanges: BsCustomDates[] = []; @@ -122,6 +126,9 @@ export abstract class BsDatepickerAbstractComponent { // eslint-disable-next-line clearDate(): void {} + // eslint-disable-next-line + setCustomDate(): void {} + // eslint-disable-next-line @typescript-eslint/no-explicit-any _stopPropagation(event: any): void { event.stopPropagation(); diff --git a/src/datepicker/bs-datepicker.config.ts b/src/datepicker/bs-datepicker.config.ts index 5ed699e070..64b5f74558 100644 --- a/src/datepicker/bs-datepicker.config.ts +++ b/src/datepicker/bs-datepicker.config.ts @@ -149,11 +149,19 @@ export class BsDatepickerConfig implements DatepickerRenderOptions { * Shows clear button */ showClearButton = false; + /** + * CustomDate clear button + */ + customDateButton?: Date = undefined; /** * Positioning of 'today' button */ todayPosition = 'center'; + /** + * Positioning of 'today' button + */ + customPosition = 'left'; /** * Positioning of 'clear' button @@ -169,6 +177,10 @@ export class BsDatepickerConfig implements DatepickerRenderOptions { * Label for 'clear' button */ clearButtonLabel = 'Clear'; + /** + * Label for custom Button + */ + customButtonLabel = 'Custom Date'; /** * Label for 'custom range' button diff --git a/src/datepicker/bs-datepicker.scss b/src/datepicker/bs-datepicker.scss index c6e6a54d95..77eaafb4c2 100644 --- a/src/datepicker/bs-datepicker.scss +++ b/src/datepicker/bs-datepicker.scss @@ -472,17 +472,23 @@ } .clear-right, + .custom-right, .today-right { flex-grow: 0; + order: 3 } .clear-left, + .custom-left, .today-left { flex-grow: 1; + order: 1 } .clear-center, + .custom-center, .today-center { flex-grow: 0.5; + order: 2 } } } diff --git a/src/datepicker/testing/bs-datepicker.spec.ts b/src/datepicker/testing/bs-datepicker.spec.ts index 3ab49d39ee..8cc42ce5bd 100644 --- a/src/datepicker/testing/bs-datepicker.spec.ts +++ b/src/datepicker/testing/bs-datepicker.spec.ts @@ -178,6 +178,22 @@ describe('datepicker:', () => { expect(buttonText.filter(button => button === clearBtnCustomLbl).length).toEqual(1); }); + it('should show custom label for custom button if set in config', () => { + const customBtnCustomLbl = 'Clear current'; + const datepickerDirective = getDatepickerDirective(fixture); + datepickerDirective.bsConfig = { + customButtonLabel: customBtnCustomLbl, + customDateButton: new Date() + }; + showDatepicker(fixture); + + const buttonText: string[] = []; + // fixture.debugElement.queryAll(By.css('button')) + Array.from(document.body.getElementsByTagName('button')) + .forEach(button => buttonText.push(button.textContent)); + expect(buttonText.filter(button => button === customBtnCustomLbl).length).toEqual(1); + }); + describe('should start with', () => { const parameters = [ @@ -257,6 +273,37 @@ describe('datepicker:', () => { }).unsubscribe(); }); + it('should set custom date', () => { + const datepicker = showDatepicker(fixture); + const datepickerContainerInstance = getDatepickerContainer(datepicker); + const customDate = new Date(2099, 11, 31); + datepickerContainerInstance.customDateBtn = customDate; + + datepickerContainerInstance[`_store`] + .select(state => state.view) + .subscribe(view => { + view.date = new Date(2020, 0, 1); + }).unsubscribe(); + fixture.detectChanges(); + + datepickerContainerInstance[`_store`] + .select(state => state.view) + .subscribe(view => { + expect(`${(view.date.getDate())}-${(view.date.getMonth())}-${(view.date.getFullYear())}`) + .not.toEqual(`${(customDate.getDate())}-${(customDate.getMonth())}-${(customDate.getFullYear())}`); + }).unsubscribe(); + + datepickerContainerInstance.setCustomDate(); + fixture.detectChanges(); + + datepickerContainerInstance[`_store`] + .select(state => state.view) + .subscribe(view => { + expect(`${(view.date.getDate())}-${(view.date.getMonth())}-${(view.date.getFullYear())}`) + .toEqual(`${(customDate.getDate())}-${(customDate.getMonth())}-${(customDate.getFullYear())}`); + }).unsubscribe(); + }); + it('should clear date', () => { const datepicker = showDatepicker(fixture); const datepickerContainerInstance = getDatepickerContainer(datepicker); diff --git a/src/datepicker/themes/bs/bs-datepicker-container.component.ts b/src/datepicker/themes/bs/bs-datepicker-container.component.ts index 1c6cfebc37..8818fb08c5 100644 --- a/src/datepicker/themes/bs/bs-datepicker-container.component.ts +++ b/src/datepicker/themes/bs/bs-datepicker-container.component.ts @@ -80,6 +80,9 @@ export class BsDatepickerContainerComponent extends BsDatepickerAbstractComponen this.showClearBtn = this._config.showClearButton; this.clearBtnLbl = this._config.clearButtonLabel; this.clearPos = this._config.clearPosition; + this.customDateBtn = this._config.customDateButton; + this.customBtnLabel = this._config.customButtonLabel; + this.customBtnPos = this._config.customPosition; this.customRangeBtnLbl = this._config.customRangeButtonLabel; this._effects?.init(this._store) // intial state options @@ -164,6 +167,10 @@ export class BsDatepickerContainerComponent extends BsDatepickerAbstractComponen this._store.dispatch(this._actions.select(undefined)); } + setCustomDate(): void { + this._store.dispatch(this._actions.select(this.customDateBtn == null ? undefined : new Date(this.customDateBtn))); + } + ngOnDestroy(): void { for (const sub of this._subs) { sub.unsubscribe(); diff --git a/src/datepicker/themes/bs/bs-datepicker-view.html b/src/datepicker/themes/bs/bs-datepicker-view.html index 0148515974..54948101f3 100644 --- a/src/datepicker/themes/bs/bs-datepicker-view.html +++ b/src/datepicker/themes/bs/bs-datepicker-view.html @@ -54,6 +54,14 @@
+
+ +
+
{{todayBtnLbl}}
-
- -
+
+ +