diff --git a/src/datepicker/datepicker-input-config.spec.ts b/src/datepicker/datepicker-input-config.spec.ts new file mode 100644 index 0000000000..7df4346ada --- /dev/null +++ b/src/datepicker/datepicker-input-config.spec.ts @@ -0,0 +1,12 @@ +import {NgbInputDatepickerConfig} from './datepicker-input-config'; + +describe('NgbInputDatepickerConfig', () => { + it('should have sensible default values', () => { + const config = new NgbInputDatepickerConfig(); + + expect(config.autoClose).toBe(true); + expect(config.container).toBeUndefined(); + expect(config.positionTarget).toBeUndefined(); + expect(config.placement).toEqual(['bottom-left', 'bottom-right', 'top-left', 'top-right']); + }); +}); diff --git a/src/datepicker/datepicker-input-config.ts b/src/datepicker/datepicker-input-config.ts new file mode 100644 index 0000000000..4366b7389e --- /dev/null +++ b/src/datepicker/datepicker-input-config.ts @@ -0,0 +1,17 @@ +import {Injectable} from '@angular/core'; + +import {PlacementArray} from '../util/positioning'; + +/** + * A configuration service for the [`NgbDatepickerInput`](#/components/datepicker/api#NgbDatepicker) component. + * + * You can inject this service, typically in your root component, and customize the values of its properties in + * order to provide default values for all the datepicker inputs used in the application. + */ +@Injectable({providedIn: 'root'}) +export class NgbInputDatepickerConfig { + autoClose: boolean | 'inside' | 'outside' = true; + container: null | 'body'; + positionTarget: string | HTMLElement; + placement: PlacementArray = ['bottom-left', 'bottom-right', 'top-left', 'top-right']; +} diff --git a/src/datepicker/datepicker-input.spec.ts b/src/datepicker/datepicker-input.spec.ts index 910bd1d55f..437b87986c 100644 --- a/src/datepicker/datepicker-input.spec.ts +++ b/src/datepicker/datepicker-input.spec.ts @@ -11,6 +11,7 @@ import {NgbDatepicker} from './datepicker'; import {NgbDateStruct} from './ngb-date-struct'; import {NgbDate} from './ngb-date'; import * as positioning from 'src/util/positioning'; +import {NgbInputDatepickerConfig} from './datepicker-input-config'; const createTestCmpt = (html: string) => createGenericTestComponent(html, TestComponent) as ComponentFixture; @@ -18,12 +19,64 @@ const createTestCmpt = (html: string) => const createTestNativeCmpt = (html: string) => createGenericTestComponent(html, TestNativeComponent) as ComponentFixture; +function expectSameValues(inputDatepicker: NgbInputDatepicker, config: NgbInputDatepickerConfig) { + ['autoClose', 'container', 'positionTarget', 'placement'].forEach( + field => expect(inputDatepicker[field]).toEqual(config[field], field)); +} + +function customizeConfig(config: NgbInputDatepickerConfig) { + config.autoClose = 'outside'; + config.container = 'body'; + config.positionTarget = 'positionTarget'; + config.placement = ['bottom-left', 'top-right']; +} + describe('NgbInputDatepicker', () => { beforeEach(() => { TestBed.configureTestingModule({declarations: [TestComponent], imports: [NgbDatepickerModule, FormsModule]}); }); + it('should initialize inputs with provided datepicker config', () => { + const defaultConfig = new NgbInputDatepickerConfig(); + const fixture = createTestCmpt(``); + + const inputDatepicker = + fixture.debugElement.query(By.directive(NgbInputDatepicker)).injector.get(NgbInputDatepicker); + expectSameValues(inputDatepicker, defaultConfig); + }); + + it('should initialize inputs with provided config', () => { + // overrideComponent should happen before any injections, so createTestCmpt will fail here + TestBed.overrideComponent(TestComponent, {set: {template: ''}}); + const config = TestBed.get(NgbInputDatepickerConfig); + customizeConfig(config); + const fixture = TestBed.createComponent(TestComponent); + fixture.detectChanges(); + + const inputDatepicker = + fixture.debugElement.query(By.directive(NgbInputDatepicker)).injector.get(NgbInputDatepicker); + expectSameValues(inputDatepicker, config); + }); + + describe('Custom config as provider', () => { + const config = new NgbInputDatepickerConfig(); + customizeConfig(config); + + beforeEach(() => { + TestBed.configureTestingModule( + {imports: [NgbDatepickerModule], providers: [{provide: NgbInputDatepickerConfig, useValue: config}]}); + }); + + it('should initialize inputs with provided config as provider', () => { + const fixture = createTestCmpt(``); + + const inputDatepicker = + fixture.debugElement.query(By.directive(NgbInputDatepicker)).injector.get(NgbInputDatepicker); + expectSameValues(inputDatepicker, config); + }); + }); + describe('open, close and toggle', () => { it('should allow controlling datepicker popup from outside', () => { diff --git a/src/datepicker/datepicker-input.ts b/src/datepicker/datepicker-input.ts index c7c25616ea..5f3b8e8915 100644 --- a/src/datepicker/datepicker-input.ts +++ b/src/datepicker/datepicker-input.ts @@ -32,6 +32,7 @@ import {NgbCalendar} from './ngb-calendar'; import {NgbDate} from './ngb-date'; import {NgbDateParserFormatter} from './ngb-date-parser-formatter'; import {NgbDateStruct} from './ngb-date-struct'; +import {NgbInputDatepickerConfig} from './datepicker-input-config'; const NGB_DATEPICKER_VALUE_ACCESSOR = { provide: NG_VALUE_ACCESSOR, @@ -258,7 +259,8 @@ export class NgbInputDatepicker implements OnChanges, private _vcRef: ViewContainerRef, private _renderer: Renderer2, private _cfr: ComponentFactoryResolver, private _ngZone: NgZone, private _service: NgbDatepickerService, private _calendar: NgbCalendar, private _dateAdapter: NgbDateAdapter, @Inject(DOCUMENT) private _document: any, - private _changeDetector: ChangeDetectorRef) { + private _changeDetector: ChangeDetectorRef, config: NgbInputDatepickerConfig) { + ['autoClose', 'container', 'positionTarget', 'placement'].forEach(input => this[input] = config[input]); this._zoneSubscription = _ngZone.onStable.subscribe(() => this._updatePopupPosition()); } diff --git a/src/datepicker/datepicker.module.ts b/src/datepicker/datepicker.module.ts index a4455b2d3e..8b4c7c7dba 100644 --- a/src/datepicker/datepicker.module.ts +++ b/src/datepicker/datepicker.module.ts @@ -21,6 +21,7 @@ export {NgbDatepickerDayView} from './datepicker-day-view'; export {NgbDatepickerNavigation} from './datepicker-navigation'; export {NgbDatepickerNavigationSelect} from './datepicker-navigation-select'; export {NgbDatepickerConfig} from './datepicker-config'; +export {NgbInputDatepickerConfig} from './datepicker-input-config'; export {NgbDatepickerI18n} from './datepicker-i18n'; export {NgbDateStruct} from './ngb-date-struct'; export {NgbDate} from './ngb-date'; diff --git a/src/index.ts b/src/index.ts index 3fe1926ebe..a207c056c7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -50,6 +50,7 @@ export { NgbDateParserFormatter, NgbDatepicker, NgbDatepickerConfig, + NgbInputDatepickerConfig, NgbDatepickerI18n, NgbDatepickerI18nHebrew, NgbDatepickerModule,