Skip to content

Commit

Permalink
feat(datepicker): use as directives (#2446)
Browse files Browse the repository at this point in the history
* feat(datepicker): use as directives too

* feat(datepicker): added outside click support

* chore(tests): ignore some tooo smart typings

* fix(datepicker): fixed outside click issues

* fix(core): fixed attaching of outside click listener
  • Loading branch information
valorkin authored Aug 17, 2017
1 parent da7d352 commit d7f9a2a
Show file tree
Hide file tree
Showing 17 changed files with 195 additions and 111 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ yarn.lock
npm-debug.log

# ignore build and dist for now
.tmp
/dist
/temp
/demo/dist
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
<pre>{{bsValue}}</pre>

<input type="text"
value="{{ bsValue | date:'yMd'}}"
bsDatepicker [(bsValue)]="bsValue">
<span style="display: inline-block">
<button class="btn btn-success" (click)="dp.toggle()">Date Picker popup</button>
<bs-datepicker #dp [(value)]="bsValue" style="display: block"></bs-datepicker>
<bs-datepicker #dp [(bsValue)]="bsValue" style="display: block"></bs-datepicker>
</span>

<br>
<br>

<pre>{{bsRangeValue}}</pre>

<input type="text"
value="{{ bsRangeValue[0] | date:'yMd'}} - {{ bsRangeValue[1] | date:'yMd'}}"
bsDaterangepicker [(bsValue)]="bsRangeValue">
<span style="display: inline-block">
<button class="btn btn-success" (click)="drp.toggle()">Date Range Picker popup</button>
<bs-daterangepicker #drp [(value)]="bsRangeValue" placement="right" style="display: block"></bs-daterangepicker>
<bs-daterangepicker #drp [(bsValue)]="bsRangeValue" placement="right" style="display: block"></bs-daterangepicker>
</span>

2 changes: 1 addition & 1 deletion demo/src/typings.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ declare const PR:any;
// declare const global:any;

declare module jasmine {
interface Matchers {
interface Matchers<T> {
toHaveCssClass(expected: any): boolean;
}
}
50 changes: 25 additions & 25 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,29 +77,29 @@
"@angular/platform-browser-dynamic": "^2.4.4",
"@angular/router": "^3.4.4",
"@angular/tsc-wrapped": "0.5.1",
"@types/jasmine": "2.5.41",
"@types/marked": "0.0.28",
"@types/node": "7.0.15",
"@types/webpack": "^2.2.2",
"@types/jasmine": "2.5.53",
"@types/marked": "0.3.0",
"@types/node": "8.0.23",
"@types/webpack": "3.0.9",
"bootstrap": "3.3.7",
"classlist-polyfill": "1.0.3",
"codecov": "2.1.0",
"codelyzer": "3.0.1",
"conventional-changelog-cli": "1.3.1",
"conventional-github-releaser": "1.1.3",
"classlist-polyfill": "1.2.0",
"codecov": "2.3.0",
"codelyzer": "3.1.2",
"conventional-changelog-cli": "1.3.2",
"conventional-github-releaser": "1.1.12",
"core-js": "^2.4.1",
"cpy": "5.0.0",
"cpy": "5.1.0",
"cpy-cli": "1.0.1",
"del-cli": "0.2.1",
"gh-pages": "0.12.0",
"del-cli": "1.1.0",
"gh-pages": "1.0.0",
"gitignore-to-glob": "0.3.0",
"google-code-prettify": "1.0.5",
"html-loader": "0.4.5",
"html-loader": "0.5.1",
"intl": "^1.2.5",
"jasmine": "2.6.0",
"jasmine-core": "2.6.1",
"jasmine": "2.7.0",
"jasmine-core": "2.7.0",
"jasmine-data-provider": "2.2.0",
"jasmine-spec-reporter": "3.2.0",
"jasmine-spec-reporter": "4.2.1",
"karma": "1.7.0",
"karma-chrome-launcher": "^2.0.0",
"karma-cli": "^1.0.1",
Expand All @@ -115,18 +115,18 @@
"ng2-page-scroll": "4.0.0-beta.7",
"ngm-cli": "0.6.1",
"npm-run-all": "4.0.2",
"protractor": "5.1.1",
"protractor": "5.1.2",
"reflect-metadata": "0.1.10",
"require-dir": "0.3.1",
"require-dir": "0.3.2",
"rxjs": "5.4.3",
"ts-helpers": "^1.1.1",
"tslint": "4.5.1",
"tslint-config-valorsoft": "1.2.0",
"typedoc": "0.5.9",
"tslint": "5.6.0",
"tslint-config-valorsoft": "2.1.0",
"typedoc": "0.8.0",
"typescript": "2.4.2",
"wallaby-webpack": "0.0.37",
"webdriver-manager": "12.0.4",
"webpack-bundle-analyzer": "2.8.2",
"zone.js": "0.8.14"
"wallaby-webpack": "0.0.39",
"webdriver-manager": "12.0.6",
"webpack-bundle-analyzer": "2.9.0",
"zone.js": "0.8.16"
}
}
2 changes: 1 addition & 1 deletion scripts/typings.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ declare const ENV:string;
declare const PR:any;

declare module jasmine {
interface Matchers {
interface Matchers<T> {
toHaveCssClass(expected: any): boolean;
}
}
63 changes: 35 additions & 28 deletions src/component-loader/component-loader.class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ export class ComponentLoader<T> {
*/
private triggers: string;

_listenOpts: ListenOptions = {};
_globalListener = Function.prototype;

/**
* Do not use this directly, it should be instanced via
* `ComponentLoadFactory.attach`
Expand Down Expand Up @@ -145,6 +148,9 @@ export class ComponentLoader<T> {
this._componentRef.changeDetectorRef.detectChanges();
this.onShown.emit(this._componentRef.instance);
}

this._registerOutsideClick();

return this._componentRef;
}

Expand Down Expand Up @@ -172,8 +178,10 @@ export class ComponentLoader<T> {

this._contentRef = null;
this._componentRef = null;
this._removeGlobalListener();

this.onHidden.emit();

return this;
}

Expand All @@ -200,36 +208,13 @@ export class ComponentLoader<T> {

public listen(listenOpts: ListenOptions): ComponentLoader<T> {
this.triggers = listenOpts.triggers || this.triggers;
this._listenOpts.outsideClick = listenOpts.outsideClick;
listenOpts.target = listenOpts.target || this._elementRef.nativeElement;

listenOpts.target = listenOpts.target || this._elementRef;
let _removeGlobalListener = Function.prototype;

const hide = () => {
if (listenOpts.hide) {
listenOpts.hide();
} else {
this.hide();
}

_removeGlobalListener();
};

const show = (registerHide: Function) => {
listenOpts.show ? listenOpts.show() : this.show();
// register hide listeners
// register outsideClick
const hide = this._listenOpts.hide = () => listenOpts.hide ? listenOpts.hide() : this.hide();
const show = this._listenOpts.show = (registerHide: Function) => {
listenOpts.show ? listenOpts.show(registerHide) : this.show(registerHide);
registerHide();
if (this._componentRef && this._componentRef.location) {
// why: should run after first event bubble
const target = this._componentRef.location;
setTimeout(() => {
_removeGlobalListener = registerOutsideClick(this._renderer, {
target,
outsideClick: listenOpts.outsideClick,
hide
});
});
}
};

const toggle = (registerHide: Function) => {
Expand All @@ -245,6 +230,28 @@ export class ComponentLoader<T> {
return this;
}

_removeGlobalListener() {
if (this._globalListener) {
this._globalListener();
this._globalListener = null;
}
}

_registerOutsideClick(): void {
if (!this._componentRef || !this._componentRef.location) {
return;
}
// why: should run after first event bubble
const target = this._componentRef.location.nativeElement;
setTimeout(() => {
this._globalListener = registerOutsideClick(this._renderer, {
targets: [target, this._elementRef.nativeElement],
outsideClick: this._listenOpts.outsideClick,
hide: () => this._listenOpts.hide()
});
});
}

public getInnerComponent(): ComponentRef<T> {
return this._innerComponent;
}
Expand Down
5 changes: 2 additions & 3 deletions src/component-loader/listen-options.model.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { ElementRef } from '@angular/core';

export interface ListenOptions {
target?: ElementRef | HTMLElement;
target?: HTMLElement;
targets?: HTMLElement[];
triggers?: string;
outsideClick?: boolean;
show?: Function;
Expand Down
37 changes: 27 additions & 10 deletions src/datepicker/bs-datepicker.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ import { Subscription } from 'rxjs/Subscription';
import 'rxjs/add/operator/filter';

@Component({
selector: 'bs-datepicker',
selector: 'bs-datepicker,[bsDatepicker]',
exportAs: 'bsDatepicker',
template: ''
template: ' '
})
export class BsDatepickerComponent implements OnInit, OnDestroy {
/**
Expand All @@ -30,6 +30,8 @@ export class BsDatepickerComponent implements OnInit, OnDestroy {
* event names.
*/
@Input() triggers = 'click';

@Input() outsideClick = true;
/**
* A selector specifying the element the popover should be appended to.
* Currently only supports "body".
Expand Down Expand Up @@ -61,8 +63,14 @@ export class BsDatepickerComponent implements OnInit, OnDestroy {
// @Input() config: BsDatePickerOptions;
// configChange: EventEmitter<BsDatePickerOptions> = new EventEmitter();

@Input() value: Date;
@Output() valueChange: EventEmitter<Date> = new EventEmitter();
_bsValue: Date;
@Input()
set bsValue(value: Date) {
this._bsValue = value;
this.bsValueChange.emit(value);
}

@Output() bsValueChange: EventEmitter<Date> = new EventEmitter();

protected subscriptions: Subscription[] = [];

Expand All @@ -79,10 +87,6 @@ export class BsDatepickerComponent implements OnInit, OnDestroy {
// Object.assign(this, _config);
this.onShown = this._datepicker.onShown;
this.onHidden = this._datepicker.onHidden;

this.valueChange
.filter(value => !!value)
.subscribe(value => this.hide());
}

/**
Expand All @@ -101,9 +105,21 @@ export class BsDatepickerComponent implements OnInit, OnDestroy {
.show({placement: this.placement});

// link with datepicker
this._datepickerRef.instance.value = this.value;
// set initial value of picker
this._datepickerRef.instance.value = this._bsValue;

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

// if date changes from picker (view -> model)
this.subscriptions.push(this._datepickerRef.instance
.valueChange.subscribe((value: Date) => this.valueChange.emit(value)));
.valueChange.subscribe((value: Date) => {
if (value === this._bsValue) {return; }
this.bsValueChange.emit(value);
this.hide();
}));
}

/**
Expand All @@ -130,6 +146,7 @@ export class BsDatepickerComponent implements OnInit, OnDestroy {

ngOnInit(): any {
this._datepicker.listen({
outsideClick: this.outsideClick,
triggers: this.triggers,
show: () => this.show()
});
Expand Down
2 changes: 2 additions & 0 deletions src/datepicker/bs-datepicker.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { BsDaterangepickerComponent } from './bs-daterangepicker.component';
import { BsDatepickerComponent } from './bs-datepicker.component';
import { ComponentLoaderFactory } from '../component-loader/component-loader.factory';
import { PositioningService } from '../positioning/positioning.service';
import { BsDatepickerDayDecoratorComponent } from './themes/bs/bs-datepicker-day-decorator.directive';

@NgModule({
imports: [CommonModule],
Expand All @@ -22,6 +23,7 @@ import { PositioningService } from '../positioning/positioning.service';
BsDatepickerViewComponent,
BsDatepickerNavigationViewComponent,
BsDatepickerDayViewComponent,
BsDatepickerDayDecoratorComponent,
BsDatepickerContainerComponent,
BsDaterangepickerContainerComponent,
BsDatepickerComponent,
Expand Down
Loading

0 comments on commit d7f9a2a

Please sign in to comment.