diff --git a/components/date-picker/date-picker.component.spec.ts b/components/date-picker/date-picker.component.spec.ts index dcb2e52657..50fae66b3d 100644 --- a/components/date-picker/date-picker.component.spec.ts +++ b/components/date-picker/date-picker.component.spec.ts @@ -3,7 +3,7 @@ import { ESCAPE } from '@angular/cdk/keycodes'; import { OverlayContainer } from '@angular/cdk/overlay'; import { registerLocaleData } from '@angular/common'; import zh from '@angular/common/locales/zh'; -import { Component, DebugElement, TemplateRef, ViewChild } from '@angular/core'; +import { ApplicationRef, Component, DebugElement, TemplateRef, ViewChild } from '@angular/core'; import { ComponentFixture, fakeAsync, flush, inject, TestBed, tick } from '@angular/core/testing'; import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { By } from '@angular/platform-browser'; @@ -489,6 +489,22 @@ describe('NzDatePickerComponent', () => { expect(result.getDate()).toBe(+cellText); })); + it('should not run change detection when inline mode is enabled and the `date-range-popup` is clicked', () => { + fixtureInstance.nzInline = true; + fixture.detectChanges(); + + const appRef = TestBed.inject(ApplicationRef); + const event = new MouseEvent('mousedown'); + + spyOn(appRef, 'tick'); + spyOn(event, 'preventDefault').and.callThrough(); + + debugElement.nativeElement.querySelector('date-range-popup').dispatchEvent(event); + + expect(appRef.tick).not.toHaveBeenCalled(); + expect(event.preventDefault).toHaveBeenCalled(); + }); + it('should support nzBackdrop', fakeAsync(() => { fixtureInstance.nzBackdrop = true; fixture.detectChanges(); diff --git a/components/date-picker/date-range-popup.component.ts b/components/date-picker/date-range-popup.component.ts index 79d21cc090..f0bad855c5 100644 --- a/components/date-picker/date-range-popup.component.ts +++ b/components/date-picker/date-range-popup.component.ts @@ -8,8 +8,10 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, + ElementRef, EventEmitter, Input, + NgZone, OnChanges, OnDestroy, OnInit, @@ -18,7 +20,7 @@ import { TemplateRef, ViewEncapsulation } from '@angular/core'; -import { merge, Subject } from 'rxjs'; +import { fromEvent, merge, Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { @@ -139,10 +141,7 @@ import { getTimeConfig, isAllowedDate, PREFIX_CLASS } from './util'; {{ name }} - `, - host: { - '(mousedown)': 'onMousedown($event)' - } + ` }) export class DateRangePopupComponent implements OnInit, OnChanges, OnDestroy { @Input() isRange!: boolean; @@ -180,7 +179,12 @@ export class DateRangePopupComponent implements OnInit, OnChanges, OnDestroy { return this.showToday || this.hasTimePicker || !!this.extraFooter || !!this.ranges; } - constructor(public datePickerService: DatePickerService, public cdr: ChangeDetectorRef) {} + constructor( + public datePickerService: DatePickerService, + public cdr: ChangeDetectorRef, + private ngZone: NgZone, + private host: ElementRef + ) {} ngOnInit(): void { merge(this.datePickerService.valueChange$, this.datePickerService.inputPartChange$) @@ -189,6 +193,12 @@ export class DateRangePopupComponent implements OnInit, OnChanges, OnDestroy { this.updateActiveDate(); this.cdr.markForCheck(); }); + + this.ngZone.runOutsideAngular(() => { + fromEvent(this.host.nativeElement, 'mousedown') + .pipe(takeUntil(this.destroy$)) + .subscribe(event => event.preventDefault()); + }); } ngOnChanges(changes: SimpleChanges): void { @@ -222,15 +232,6 @@ export class DateRangePopupComponent implements OnInit, OnChanges, OnDestroy { ); } - /** - * Prevent input losing focus when click panel - * - * @param event - */ - onMousedown(event: MouseEvent): void { - event.preventDefault(); - } - onClickOk(): void { const inputIndex = { left: 0, right: 1 }[this.datePickerService.activeInput]; const value: CandyDate = this.isRange