diff --git a/src/components/dropdown/nz-dropdown-button.component.ts b/src/components/dropdown/nz-dropdown-button.component.ts
index 5181cccf488..7710976de3a 100644
--- a/src/components/dropdown/nz-dropdown-button.component.ts
+++ b/src/components/dropdown/nz-dropdown-button.component.ts
@@ -74,24 +74,21 @@ export class NzDropDownButtonComponent extends NzDropDownComponent implements On
@Output() nzClick = new EventEmitter();
@ViewChild(NzDropDownDirective) _nzOrigin;
- ngOnInit() {
- debounceTime.call(this._$mouseSubject, 300).subscribe((data: boolean) => {
- if (this.nzDisable) {
- return;
+ _onVisibleChange = (visible: boolean) => {
+ if (this.nzDisable) {
+ return;
+ }
+ if (visible) {
+ if (!this._triggerWidth) {
+ this._setTriggerWidth();
}
- this.nzVisible = data;
- if (this.nzVisible) {
- if (!this._triggerWidth) {
- this._setTriggerWidth();
- }
- }
- this.nzVisibleChange.emit(this.nzVisible);
- });
- this._nzMenu.setDropDown(true);
+ }
+ this.nzVisible = visible;
+ this._changeDetector.markForCheck();
}
/** rewrite afterViewInit hook */
ngAfterViewInit() {
-
+ this._startSubscribe(this.nzVisibleChange.asObservable());
}
}
diff --git a/src/components/dropdown/nz-dropdown.component.ts b/src/components/dropdown/nz-dropdown.component.ts
index 3a3c98525e2..79d1ccb57d1 100644
--- a/src/components/dropdown/nz-dropdown.component.ts
+++ b/src/components/dropdown/nz-dropdown.component.ts
@@ -7,10 +7,16 @@ import {
Renderer2,
ContentChild,
Output,
- EventEmitter, AfterViewInit
+ EventEmitter,
+ AfterViewInit,
+ ChangeDetectionStrategy,
+ ChangeDetectorRef
} from '@angular/core';
-import { Subject } from 'rxjs/Subject';
+import { merge } from 'rxjs/observable/merge';
import { debounceTime } from 'rxjs/operator/debounceTime';
+import { Observable } from 'rxjs/Observable';
+import { Subscription } from 'rxjs/Subscription';
+import { Observer } from 'rxjs/Observer'
import { NzMenuComponent } from '../menu/nz-menu.component';
import { DropDownAnimation } from '../core/animation/dropdown-animations';
import { NzDropDownDirective } from './nz-dropdown.directive';
@@ -25,6 +31,7 @@ export type NzPlacement = 'bottomLeft' | 'bottomCenter' | 'bottomRight' | 'topLe
animations : [
DropDownAnimation
],
+ changeDetection: ChangeDetectionStrategy.OnPush,
template : `
@@ -57,10 +64,10 @@ export type NzPlacement = 'bottomLeft' | 'bottomCenter' | 'bottomRight' | 'topLe
export class NzDropDownComponent implements OnInit, OnDestroy, AfterViewInit {
_triggerWidth = 0;
- _$mouseSubject = new Subject();
_placement: NzPlacement = 'bottomLeft';
_dropDownPosition: 'top' | 'bottom' = 'bottom';
_positions: ConnectionPositionPair[] = [ ...DEFAULT_DROPDOWN_POSITIONS ];
+ _subscription: Subscription;
@ContentChild(NzDropDownDirective) _nzOrigin;
@ContentChild(NzMenuComponent) _nzMenu;
@Input() nzTrigger: 'click' | 'hover' = 'hover';
@@ -97,6 +104,14 @@ export class NzDropDownComponent implements OnInit, OnDestroy, AfterViewInit {
}
}
+ _hide() {
+ this.nzVisibleChange.emit(false);
+ }
+
+ _show() {
+ this.nzVisibleChange.emit(true);
+ }
+
_onPositionChange(position) {
this._dropDownPosition = position.connectionPair.originY;
}
@@ -112,49 +127,67 @@ export class NzDropDownComponent implements OnInit, OnDestroy, AfterViewInit {
this._triggerWidth = this._nzOrigin.elementRef.nativeElement.getBoundingClientRect().width;
}
- _show() {
- this._$mouseSubject.next(true);
+ _onVisibleChange = (visible: boolean) => {
+ if (visible) {
+ if (!this._triggerWidth) {
+ this._setTriggerWidth();
+ }
+ }
+ this.nzVisible = visible;
+ this._changeDetector.markForCheck();
}
- _hide() {
- this._$mouseSubject.next(false);
+ _startSubscribe(observable$: Observable) {
+ this._subscription = observable$
+ .subscribe(this._onVisibleChange)
}
ngOnInit() {
- debounceTime.call(this._$mouseSubject, 300).subscribe((data: boolean) => {
- this.nzVisible = data;
- if (this.nzVisible) {
- if (!this._triggerWidth) {
- this._setTriggerWidth();
- }
- }
- this.nzVisibleChange.emit(this.nzVisible);
- });
this._nzMenu.setDropDown(true);
}
ngOnDestroy() {
- this._$mouseSubject.unsubscribe();
+ this._subscription.unsubscribe();
}
-
ngAfterViewInit() {
+ let mouse$: Observable
if (this.nzTrigger === 'hover') {
- this._renderer.listen(this._nzOrigin.elementRef.nativeElement, 'mouseenter', () => this._show());
- this._renderer.listen(this._nzOrigin.elementRef.nativeElement, 'mouseleave', () => this._hide());
+ mouse$ = Observable.create((observer: Observer) => {
+ const disposeMouseEnter = this._renderer.listen(this._nzOrigin.elementRef.nativeElement, 'mouseenter', () => {
+ observer.next(true);
+ });
+ const disposeMouseLeave = this._renderer.listen(this._nzOrigin.elementRef.nativeElement, 'mouseleave', () => {
+ observer.next(false);
+ });
+ return () => {
+ disposeMouseEnter();
+ disposeMouseLeave();
+ }
+ });
}
if (this.nzTrigger === 'click') {
- this._renderer.listen(this._nzOrigin.elementRef.nativeElement, 'click', (e) => {
- e.preventDefault();
- this._show()
+ mouse$ = Observable.create((observer: Observer) => {
+ const dispose = this._renderer.listen(this._nzOrigin.elementRef.nativeElement, 'click', (e) => {
+ e.preventDefault();
+ observer.next(true);
+ });
+ return () => dispose();
});
}
+ const observable$ = debounceTime.call(
+ merge(
+ mouse$,
+ this.nzVisibleChange.asObservable()
+ )
+ , 300);
+ this._startSubscribe(observable$);
}
get _hasBackdrop() {
return this.nzTrigger === 'click';
}
- constructor(private _renderer: Renderer2) {
+ constructor(private _renderer: Renderer2, protected _changeDetector: ChangeDetectorRef) {
}
}