Skip to content

Commit

Permalink
feat(datepicker): Add directive for inline datepicker (#3956)
Browse files Browse the repository at this point in the history
* feat(datepicker): Add directive for inline datepicker

Closes #3955

* feat(datepicker): add support to set custom classes on specific dates

Closes #3958

* Revert "feat(datepicker): add support to set custom classes on specific dates"

This reverts commit 47a1a11.

* feat(datepicker): resolve conflicts

* fix(datepicker): fix tslint

* fix(datepicker): clean up

* fix(datepicker): add base spec for inline datepicker

* fix(common): fix imports for system js
  • Loading branch information
martintro authored and valorkin committed Jan 18, 2019
1 parent 89f7265 commit d9a89b4
Show file tree
Hide file tree
Showing 14 changed files with 354 additions and 16 deletions.
18 changes: 16 additions & 2 deletions demo/src/app/components/+datepicker/datepicker-section.list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { DemoDatepickerConfigMethodComponent } from './demos/config-method/confi
import { DemoDatePickerConfigObjectComponent } from './demos/config-object/config-object';
import { DemoDatePickerCustomFormatComponent } from './demos/custom-format/custom-format';
import { DemoDatepickerDateInitialStateComponent } from './demos/date-initial-state/date-initial-state';
import { DemoDatepickerDaysDisabledComponent } from './demos/disable-days/disable-days';
import { DemoDatepickerInlineComponent } from './demos/inline-datepicker/inline-datepicker.component';
import { DemoDatepickerDisabledComponent } from './demos/disabled/disabled.component';
import { DemoDatepickerFormsComponent } from './demos/forms/forms.component';
import { DemoDatepickerHideOnScrollComponent } from './demos/hide-on-scroll/hide-on-scroll';
Expand All @@ -17,6 +19,7 @@ import { DemoDatepickerMinModeComponent } from './demos/min-mode/min-mode.compon
import { DemoDatepickerOutsideClickComponent } from './demos/outside-click/outside-click';
import { DemoDatepickerPlacementComponent } from './demos/placement/placement';
import { DemoDatepickerReactiveFormsComponent } from './demos/reactive-forms/reactive-forms.component';

import {
DemoDatePickerSelectDatesFromOtherMonthsComponent
} from './demos/select-dates-from-other-months/select-dates-from-other-months';
Expand All @@ -33,8 +36,6 @@ import {
NgApiDocComponent,
NgApiDocConfigComponent
} from '../../docs/api-docs';
import { DemoDatepickerDaysDisabledComponent } from './demos/disable-days/disable-days';


export const demoComponentContent: ContentSection[] = [
{
Expand Down Expand Up @@ -70,6 +71,14 @@ export const demoComponentContent: ContentSection[] = [
`,
outlet: DemoDatepickerBasicComponent
},
{
title: 'Inline Datepicker',
anchor: 'inline-datepicker',
component: require('!!raw-loader?lang=typescript!./demos/inline-datepicker/inline-datepicker.component.ts'),
html: require('!!raw-loader?lang=markup!./demos/inline-datepicker/inline-datepicker.component.html'),
description: `<p>with initial state set by <code>bsInlineValue</code> property</p>`,
outlet: DemoDatepickerInlineComponent
},
{
title: 'Initial state',
anchor: 'date-initial-state',
Expand Down Expand Up @@ -315,6 +324,11 @@ export const demoComponentContent: ContentSection[] = [
anchor: 'bs-daterangepicker',
outlet: NgApiDocComponent
},
{
title: 'BsDatepickerInlineDirective',
anchor: 'bs-datepicker-inline',
outlet: NgApiDocComponent
},
{
title: 'BsDatepickerConfig',
anchor: 'bs-datepicker-config',
Expand Down
1 change: 0 additions & 1 deletion demo/src/app/components/+datepicker/demos/basic/basic.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,3 @@
bsDaterangepicker>
</div>
</div>

4 changes: 4 additions & 0 deletions demo/src/app/components/+datepicker/demos/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,17 @@ import { DemoDatepickerDaysDisabledComponent } from './disable-days/disable-days
import { DemoDatepickerDisabledComponent } from './disabled/disabled.component';
import { DemoDatepickerFormsComponent } from './forms/forms.component';
import { DemoDatepickerHideOnScrollComponent } from './hide-on-scroll/hide-on-scroll';
import { DemoDatepickerInlineComponent } from './inline-datepicker/inline-datepicker.component';
import { DemoDatepickerMinMaxComponent } from './min-max/min-max.component';
import { DemoDatepickerMinModeComponent } from './min-mode/min-mode.component';
import { DemoDatepickerOutsideClickComponent } from './outside-click/outside-click';
import { DemoDatepickerPlacementComponent } from './placement/placement';
import { DemoDatepickerReactiveFormsComponent } from './reactive-forms/reactive-forms.component';

import {
DemoDatePickerSelectDatesFromOtherMonthsComponent
} from './select-dates-from-other-months/select-dates-from-other-months';

import { DemoDatePickerSelectWeekComponent } from './select-week/select-week';
import { DemoDatepickerTriggersCustomComponent } from './triggers-custom/triggers-custom';
import { DemoDatepickerTriggersManualComponent } from './triggers-manual/triggers-manual';
Expand All @@ -42,6 +45,7 @@ export const DEMO_COMPONENTS = [
DemoDatepickerDisabledComponent,
DemoDatepickerFormsComponent,
DemoDatepickerHideOnScrollComponent,
DemoDatepickerInlineComponent,
DemoDatepickerMinMaxComponent,
DemoDatepickerMinModeComponent,
DemoDatepickerOutsideClickComponent,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<div class="row">
<div class="col-xs-12 col-12 col-md-4 form-group">
<bs-datepicker-inline [bsValue]="bsInlineValue"></bs-datepicker-inline>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Component } from '@angular/core';

@Component({
selector: 'demo-datepicker-inline',
templateUrl: './inline-datepicker.component.html'
})
export class DemoDatepickerInlineComponent {
bsInlineValue = new Date();
}
77 changes: 77 additions & 0 deletions demo/src/ng-api-doc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -659,6 +659,62 @@ export const ngdoc: any = {
"methods": [],
"properties": []
},
"BsDatepickerInlineDirective": {
"fileName": "src/datepicker/bs-datepicker-inline.component.ts",
"className": "BsDatepickerInlineDirective",
"description": "",
"selector": "bs-datepicker-inline",
"exportAs": "bsDatepickerInline",
"inputs": [
{
"name": "bsConfig",
"type": "Partial<BsDatepickerInlineConfig>",
"description": "<p>Config object for datepicker</p>\n"
},
{
"name": "bsValue",
"type": "Date",
"description": "<p>Initial value of datepicker</p>\n"
},
{
"name": "isDisabled",
"type": "boolean",
"description": "<p>Indicates whether datepicker is enabled or not</p>\n"
},
{
"name": "maxDate",
"type": "Date",
"description": "<p>Maximum date which is available for selection</p>\n"
},
{
"name": "minDate",
"type": "Date",
"description": "<p>Minimum date which is available for selection</p>\n"
}
],
"outputs": [
{
"name": "bsValueChange",
"description": "<p>Emits when datepicker value has been changed</p>\n"
}
],
"properties": [],
"methods": [
{
"name": "setConfig",
"description": "<p>Set config for datepicker</p>\n",
"args": [],
"returnType": "void"
}
]
},
"BsDatepickerInlineConfig": {
"fileName": "src/datepicker/bs-datepicker-inline.config.ts",
"className": "BsDatepickerInlineConfig",
"description": "",
"methods": [],
"properties": []
},
"BsDatepickerInputDirective": {
"fileName": "src/datepicker/bs-datepicker-input.directive.ts",
"className": "BsDatepickerInputDirective",
Expand Down Expand Up @@ -1543,6 +1599,16 @@ export const ngdoc: any = {
"properties": [],
"methods": []
},
"BsDatepickerInlineContainerComponent": {
"fileName": "src/datepicker/themes/bs/bs-datepicker-inline-container.component.ts",
"className": "BsDatepickerInlineContainerComponent",
"description": "",
"selector": "bs-datepicker-inline-container",
"inputs": [],
"outputs": [],
"properties": [],
"methods": []
},
"BsDatepickerNavigationViewComponent": {
"fileName": "src/datepicker/themes/bs/bs-datepicker-navigation-view.component.ts",
"className": "BsDatepickerNavigationViewComponent",
Expand Down Expand Up @@ -2887,6 +2953,11 @@ export const ngdoc: any = {
"type": "boolean",
"description": "<p>if true hours and minutes fields will be disabled </p>\n"
},
{
"name": "disabled",
"type": "boolean",
"description": "<p>if true hours and minutes fields will be disabled </p>\n"
},
{
"name": "hourStep",
"type": "number",
Expand Down Expand Up @@ -2975,6 +3046,12 @@ export const ngdoc: any = {
"type": "boolean",
"description": "<p>if true hours and minutes fields will be disabled </p>\n"
},
{
"name": "disabled",
"defaultValue": "false",
"type": "boolean",
"description": "<p>if true hours and minutes fields will be disabled </p>\n"
},
{
"name": "hourStep",
"defaultValue": "1",
Expand Down
2 changes: 1 addition & 1 deletion src/component-loader/component-loader.class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export class ComponentLoader<T> {
}

// todo: add behaviour: to target element, `body`, custom element
to(container?: string): ComponentLoader<T> {
to(container?: string | ElementRef): ComponentLoader<T> {
this.container = container || this.container;

return this;
Expand Down
126 changes: 126 additions & 0 deletions src/datepicker/bs-datepicker-inline.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import {
ComponentRef, Directive, ElementRef, EventEmitter, Input, OnChanges,
OnDestroy, OnInit, Output, Renderer2, SimpleChanges, ViewContainerRef
} from '@angular/core';
import { ComponentLoader, ComponentLoaderFactory } from 'ngx-bootstrap/component-loader';
import { BsDatepickerInlineContainerComponent } from './themes/bs/bs-datepicker-inline-container.component';
import { Subscription } from 'rxjs';
import { BsDatepickerInlineConfig } from './bs-datepicker-inline.config';
import { BsDatepickerConfig } from './bs-datepicker.config';

@Directive({
selector: 'bs-datepicker-inline',
exportAs: 'bsDatepickerInline'
})
export class BsDatepickerInlineDirective implements OnInit, OnDestroy, OnChanges {
_bsValue: Date;
/**
* Initial value of datepicker
*/
@Input()
set bsValue(value: Date) {
if (this._bsValue === value) {
return;
}
this._bsValue = value;
this.bsValueChange.emit(value);
}

/**
* Config object for datepicker
*/
@Input() bsConfig: Partial<BsDatepickerInlineConfig>;
/**
* Indicates whether datepicker is enabled or not
*/
@Input() isDisabled: boolean;
/**
* Minimum date which is available for selection
*/
@Input() minDate: Date;
/**
* Maximum date which is available for selection
*/
@Input() maxDate: Date;
/**
* Emits when datepicker value has been changed
*/
@Output() bsValueChange: EventEmitter<Date> = new EventEmitter();

protected _subs: Subscription[] = [];

private _datepicker: ComponentLoader<BsDatepickerInlineContainerComponent>;
private _datepickerRef: ComponentRef<BsDatepickerInlineContainerComponent>;

constructor(public _config: BsDatepickerInlineConfig,
private _elementRef: ElementRef,
_renderer: Renderer2,
_viewContainerRef: ViewContainerRef,
cis: ComponentLoaderFactory) {
// todo: assign only subset of fields
Object.assign(this, this._config);
this._datepicker = cis.createLoader<BsDatepickerInlineContainerComponent>(
_elementRef,
_viewContainerRef,
_renderer
);
}

ngOnInit(): void {
this.setConfig();

this._datepickerRef = this._datepicker
.provide({provide: BsDatepickerConfig, useValue: this._config})
.attach(BsDatepickerInlineContainerComponent)
.to(this._elementRef)
.show();

// if date changes from external source (model -> view)
this._subs.push(
this.bsValueChange.subscribe((value: Date) => {
this._datepickerRef.instance.value = value;
})
);

// if date changes from picker (view -> model)
this._subs.push(
this._datepickerRef.instance.valueChange.subscribe((value: Date) => {
this.bsValue = value;
})
);
}

ngOnChanges(changes: SimpleChanges): void {
if (!this._datepickerRef || !this._datepickerRef.instance) {
return;
}

if (changes.minDate) {
this._datepickerRef.instance.minDate = this.minDate;
}

if (changes.maxDate) {
this._datepickerRef.instance.maxDate = this.maxDate;
}

if (changes.isDisabled) {
this._datepickerRef.instance.isDisabled = this.isDisabled;
}
}

/**
* Set config for datepicker
*/
setConfig(): void {
this._config = Object.assign({}, this._config, this.bsConfig, {
value: this._bsValue,
isDisabled: this.isDisabled,
minDate: this.minDate || this.bsConfig && this.bsConfig.minDate,
maxDate: this.maxDate || this.bsConfig && this.bsConfig.maxDate
});
}

ngOnDestroy(): any {
this._datepicker.dispose();
}
}
5 changes: 5 additions & 0 deletions src/datepicker/bs-datepicker-inline.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Injectable } from '@angular/core';
import { BsDatepickerConfig } from './bs-datepicker.config';

@Injectable()
export class BsDatepickerInlineConfig extends BsDatepickerConfig { }
12 changes: 10 additions & 2 deletions src/datepicker/bs-datepicker.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { BsDatepickerConfig } from './bs-datepicker.config';
import { BsDaterangepickerInputDirective } from './bs-daterangepicker-input.directive';
import { BsDaterangepickerDirective } from './bs-daterangepicker.component';
import { BsDaterangepickerConfig } from './bs-daterangepicker.config';
import { BsDatepickerInlineDirective } from './bs-datepicker-inline.component';
import { BsDatepickerInlineConfig } from './bs-datepicker-inline.config';

import { BsLocaleService } from './bs-locale.service';
import { BsDatepickerActions } from './reducer/bs-datepicker.actions';
Expand All @@ -25,16 +27,20 @@ import { BsDaysCalendarViewComponent } from './themes/bs/bs-days-calendar-view.c
import { BsMonthCalendarViewComponent } from './themes/bs/bs-months-calendar-view.component';
import { BsTimepickerViewComponent } from './themes/bs/bs-timepicker-view.component';
import { BsYearsCalendarViewComponent } from './themes/bs/bs-years-calendar-view.component';
import { BsDatepickerInlineContainerComponent } from './themes/bs/bs-datepicker-inline-container.component';

const _exports = [
BsDatepickerContainerComponent,
BsDaterangepickerContainerComponent,
BsDatepickerInlineContainerComponent,

BsDatepickerDirective,
BsDatepickerInputDirective,

BsDaterangepickerInputDirective,
BsDaterangepickerDirective
BsDaterangepickerDirective,

BsDatepickerInlineDirective
];

@NgModule({
Expand All @@ -56,7 +62,8 @@ const _exports = [
],
entryComponents: [
BsDatepickerContainerComponent,
BsDaterangepickerContainerComponent
BsDaterangepickerContainerComponent,
BsDatepickerInlineContainerComponent
],
exports: _exports
})
Expand All @@ -71,6 +78,7 @@ export class BsDatepickerModule {
BsDatepickerActions,
BsDatepickerConfig,
BsDaterangepickerConfig,
BsDatepickerInlineConfig,
BsDatepickerEffects,
BsLocaleService
]
Expand Down
Loading

0 comments on commit d9a89b4

Please sign in to comment.