From 7785525e25662df0197d137d5cf4c2f89ec7e987 Mon Sep 17 00:00:00 2001 From: vthinkxie Date: Tue, 16 Jul 2019 12:20:32 +0800 Subject: [PATCH] fix(module:table): fix table scrollbar bug (#3801) close #3796 --- .../nz-measure-scrollbar.service.module.ts | 12 ----- .../services/nz-measure-scrollbar.service.ts | 53 ------------------ components/core/services/public-api.ts | 2 - components/core/util/measure-scrollbar.ts | 54 +++++++++++++++++++ components/core/util/public-api.ts | 1 + components/modal/nz-modal.spec.ts | 21 +++----- components/table/nz-table.component.ts | 23 ++++---- components/table/nz-table.module.ts | 3 +- components/table/nz-tbody.spec.ts | 4 +- components/table/nz-thead.spec.ts | 4 +- components/table/nz-tr.spec.ts | 4 +- package.json | 2 +- 12 files changed, 81 insertions(+), 102 deletions(-) delete mode 100644 components/core/services/nz-measure-scrollbar.service.module.ts delete mode 100644 components/core/services/nz-measure-scrollbar.service.ts create mode 100644 components/core/util/measure-scrollbar.ts diff --git a/components/core/services/nz-measure-scrollbar.service.module.ts b/components/core/services/nz-measure-scrollbar.service.module.ts deleted file mode 100644 index 90bd1096028..00000000000 --- a/components/core/services/nz-measure-scrollbar.service.module.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * @license - * Copyright Alibaba.com All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE - */ - -import { NgModule } from '@angular/core'; - -@NgModule() -export class NzMeasureScrollbarServiceModule {} diff --git a/components/core/services/nz-measure-scrollbar.service.ts b/components/core/services/nz-measure-scrollbar.service.ts deleted file mode 100644 index be00d823e70..00000000000 --- a/components/core/services/nz-measure-scrollbar.service.ts +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @license - * Copyright Alibaba.com All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE - */ - -import { DOCUMENT } from '@angular/common'; -import { Inject, Injectable } from '@angular/core'; -import { IndexableObject } from '../types/indexable'; -import { isNotNil } from '../util/check'; -import { NzMeasureScrollbarServiceModule } from './nz-measure-scrollbar.service.module'; - -@Injectable({ - providedIn: NzMeasureScrollbarServiceModule -}) -export class NzMeasureScrollbarService { - private _scrollbarWidth: number; - private scrollbarMeasure: IndexableObject = { - position: 'absolute', - top: '-9999px', - width: '50px', - height: '50px', - overflow: 'scroll' - }; - - get scrollBarWidth(): number { - if (isNotNil(this._scrollbarWidth)) { - return this._scrollbarWidth; - } - this.initScrollBarWidth(); - return this._scrollbarWidth; - } - - initScrollBarWidth(): void { - const scrollDiv = this.document.createElement('div'); - for (const scrollProp in this.scrollbarMeasure) { - if (this.scrollbarMeasure.hasOwnProperty(scrollProp)) { - scrollDiv.style[scrollProp] = this.scrollbarMeasure[scrollProp]; - } - } - this.document.body.appendChild(scrollDiv); - const width = scrollDiv.offsetWidth - scrollDiv.clientWidth; - this.document.body.removeChild(scrollDiv); - this._scrollbarWidth = width; - } - - // tslint:disable-next-line:no-any - constructor(@Inject(DOCUMENT) private document: any) { - this.initScrollBarWidth(); - } -} diff --git a/components/core/services/public-api.ts b/components/core/services/public-api.ts index 963cbe6bcec..e5e00551525 100644 --- a/components/core/services/public-api.ts +++ b/components/core/services/public-api.ts @@ -6,8 +6,6 @@ * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE */ -export * from './nz-measure-scrollbar.service'; -export * from './nz-measure-scrollbar.service.module'; export * from './update-host-class.service'; export * from './nz-copy-to-clipboard.service'; export * from './nz-copy-to-clipboard.service.module'; diff --git a/components/core/util/measure-scrollbar.ts b/components/core/util/measure-scrollbar.ts new file mode 100644 index 00000000000..bccc3d9b233 --- /dev/null +++ b/components/core/util/measure-scrollbar.ts @@ -0,0 +1,54 @@ +/** + * @license + * Copyright Alibaba.com All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE + */ + +export function measureScrollbar(direction: 'vertical' | 'horizontal' = 'vertical', prefix: string = 'ant'): number { + let scrollbarVerticalSize; + let scrollbarHorizontalSize; + + // Measure scrollbar width for padding body during modal show/hide + const scrollbarMeasure = { + position: 'absolute', + top: '-9999px', + width: '50px', + height: '50px' + }; + if (typeof document === 'undefined' || typeof window === 'undefined') { + return 0; + } + const isVertical = direction === 'vertical'; + if (isVertical && scrollbarVerticalSize) { + return scrollbarVerticalSize; + } else if (!isVertical && scrollbarHorizontalSize) { + return scrollbarHorizontalSize; + } + const scrollDiv = document.createElement('div'); + Object.keys(scrollbarMeasure).forEach(scrollProp => { + // @ts-ignore + scrollDiv.style[scrollProp] = scrollbarMeasure[scrollProp]; + }); + // apply hide scrollbar className ahead + scrollDiv.className = `${prefix}-hide-scrollbar scroll-div-append-to-body`; + // Append related overflow style + if (isVertical) { + scrollDiv.style.overflowY = 'scroll'; + } else { + scrollDiv.style.overflowX = 'scroll'; + } + document.body.appendChild(scrollDiv); + let size = 0; + if (isVertical) { + size = scrollDiv.offsetWidth - scrollDiv.clientWidth; + scrollbarVerticalSize = size; + } else { + size = scrollDiv.offsetHeight - scrollDiv.clientHeight; + scrollbarHorizontalSize = size; + } + + document.body.removeChild(scrollDiv); + return size; +} diff --git a/components/core/util/public-api.ts b/components/core/util/public-api.ts index 010dc5e55e4..7e48954f37a 100644 --- a/components/core/util/public-api.ts +++ b/components/core/util/public-api.ts @@ -20,3 +20,4 @@ export * from './throttleByAnimationFrame'; export * from './time'; export * from './style-checke'; export * from './text-measure'; +export * from './measure-scrollbar'; diff --git a/components/modal/nz-modal.spec.ts b/components/modal/nz-modal.spec.ts index 509b3e0d8f7..dc996471117 100644 --- a/components/modal/nz-modal.spec.ts +++ b/components/modal/nz-modal.spec.ts @@ -9,7 +9,7 @@ import { BrowserDynamicTestingModule } from '@angular/platform-browser-dynamic/t import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { NzButtonComponent, NzButtonModule } from 'ng-zorro-antd/button'; -import { dispatchFakeEvent, dispatchKeyboardEvent, NzMeasureScrollbarService } from 'ng-zorro-antd/core'; +import { dispatchFakeEvent, dispatchKeyboardEvent } from 'ng-zorro-antd/core'; import { NzI18nService } from 'ng-zorro-antd/i18n'; import { NzIconTestModule } from 'ng-zorro-antd/icon/testing'; import en_US from '../i18n/languages/en_US'; @@ -33,8 +33,7 @@ describe('modal testing (legacy)', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [NoopAnimationsModule, NzButtonModule, NzModalModule], - declarations: [NzDemoModalAsyncComponent], - providers: [NzMeasureScrollbarService] + declarations: [NzDemoModalAsyncComponent] }).compileComponents(); })); @@ -73,8 +72,7 @@ describe('modal testing (legacy)', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [NoopAnimationsModule, NzButtonModule, NzModalModule], - declarations: [NzDemoModalConfirmPromiseComponent], - providers: [NzMeasureScrollbarService] + declarations: [NzDemoModalConfirmPromiseComponent] }).compileComponents(); })); @@ -123,8 +121,7 @@ describe('modal testing (legacy)', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [NoopAnimationsModule, NzModalModule, NzIconTestModule], - declarations: [TestBasicServiceComponent], - providers: [NzMeasureScrollbarService] + declarations: [TestBasicServiceComponent] }).compileComponents(); })); @@ -226,8 +223,7 @@ describe('modal testing (legacy)', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [NoopAnimationsModule, NzModalModule], - declarations: [TestVaryServiceComponent, TestVaryServiceCustomComponent], - providers: [NzMeasureScrollbarService] + declarations: [TestVaryServiceComponent, TestVaryServiceCustomComponent] }); TestBed.overrideModule(BrowserDynamicTestingModule, { set: { entryComponents: [TestVaryServiceCustomComponent] } @@ -278,8 +274,7 @@ describe('modal testing (legacy)', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [NoopAnimationsModule, NzModalModule], - declarations: [TestConfirmModalComponent, TestConfirmCustomComponent], - providers: [NzMeasureScrollbarService] + declarations: [TestConfirmModalComponent, TestConfirmCustomComponent] }).compileComponents(); TestBed.overrideModule(BrowserDynamicTestingModule, { @@ -374,8 +369,7 @@ describe('modal testing (legacy)', () => { const injector = TestBed.configureTestingModule({ imports: [NoopAnimationsModule, NzButtonModule, NzModalModule], - declarations: [NzDemoModalAsyncComponent], - providers: [NzMeasureScrollbarService] + declarations: [NzDemoModalAsyncComponent] }); fixture = TestBed.createComponent(NzDemoModalAsyncComponent); const comp = fixture.componentInstance as NzDemoModalAsyncComponent; @@ -448,7 +442,6 @@ describe('NzModal', () => { beforeEach(fakeAsync(() => { TestBed.configureTestingModule({ imports: [NoopAnimationsModule, NzModalModule], - providers: [NzMeasureScrollbarService], declarations: [NzDemoModalBasicComponent, NzDemoModalMaskComponent, ModalByServiceComponent] }); diff --git a/components/table/nz-table.component.ts b/components/table/nz-table.component.ts index 5d11193b5e1..02df8da26ab 100644 --- a/components/table/nz-table.component.ts +++ b/components/table/nz-table.component.ts @@ -35,7 +35,7 @@ import { import { fromEvent, merge, EMPTY, Subject } from 'rxjs'; import { flatMap, startWith, takeUntil } from 'rxjs/operators'; -import { InputBoolean, InputNumber, NzMeasureScrollbarService, NzSizeMDSType } from 'ng-zorro-antd/core'; +import { measureScrollbar, InputBoolean, InputNumber, NzSizeMDSType } from 'ng-zorro-antd/core'; import { NzI18nService } from 'ng-zorro-antd/i18n'; import { NzThComponent } from './nz-th.component'; @@ -196,13 +196,19 @@ export class NzTableComponent implements OnInit, AfterViewInit, OnDestr } fitScrollBar(): void { - const scrollbarWidth = this.nzMeasureScrollbarService.scrollBarWidth; - if (scrollbarWidth) { - this.headerBottomStyle = { - marginBottom: `-${scrollbarWidth}px`, - paddingBottom: `0px` - }; - this.cdr.markForCheck(); + if (this.nzScroll.y) { + const scrollbarWidth = measureScrollbar('vertical'); + const scrollbarWidthOfHeader = measureScrollbar('horizontal', 'ant-table'); + // Add negative margin bottom for scroll bar overflow bug + if (scrollbarWidthOfHeader > 0) { + this.headerBottomStyle = { + marginBottom: `-${scrollbarWidthOfHeader}px`, + paddingBottom: '0px', + overflowX: 'scroll', + overflowY: `${scrollbarWidth === 0 ? 'hidden' : 'scroll'}` + }; + this.cdr.markForCheck(); + } } } @@ -228,7 +234,6 @@ export class NzTableComponent implements OnInit, AfterViewInit, OnDestr private renderer: Renderer2, private ngZone: NgZone, private cdr: ChangeDetectorRef, - private nzMeasureScrollbarService: NzMeasureScrollbarService, private i18n: NzI18nService, private platform: Platform, elementRef: ElementRef diff --git a/components/table/nz-table.module.ts b/components/table/nz-table.module.ts index 5607eef6687..b5088c8e19e 100644 --- a/components/table/nz-table.module.ts +++ b/components/table/nz-table.module.ts @@ -12,7 +12,7 @@ import { NgModule } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { NzCheckboxModule } from 'ng-zorro-antd/checkbox'; -import { NzAddOnModule, NzMeasureScrollbarServiceModule } from 'ng-zorro-antd/core'; +import { NzAddOnModule } from 'ng-zorro-antd/core'; import { NzDropDownModule } from 'ng-zorro-antd/dropdown'; import { NzEmptyModule } from 'ng-zorro-antd/empty'; import { NzI18nModule } from 'ng-zorro-antd/i18n'; @@ -50,7 +50,6 @@ import { NzVirtualScrollDirective } from './nz-virtual-scroll.directive'; NzVirtualScrollDirective ], imports: [ - NzMeasureScrollbarServiceModule, NzMenuModule, FormsModule, NzAddOnModule, diff --git a/components/table/nz-tbody.spec.ts b/components/table/nz-tbody.spec.ts index c0022cfd829..ddc5e61402d 100644 --- a/components/table/nz-tbody.spec.ts +++ b/components/table/nz-tbody.spec.ts @@ -1,7 +1,6 @@ import { Component, DebugElement } from '@angular/core'; import { fakeAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; -import { NzMeasureScrollbarService } from 'ng-zorro-antd/core'; import { NzTableModule } from './nz-table.module'; import { NzTbodyDirective } from './nz-tbody.directive'; @@ -9,8 +8,7 @@ describe('nz-tbody', () => { beforeEach(fakeAsync(() => { TestBed.configureTestingModule({ imports: [NzTableModule], - declarations: [NzTbodyTestTableComponent, NzTbodyTestNzTableComponent], - providers: [NzMeasureScrollbarService] + declarations: [NzTbodyTestTableComponent, NzTbodyTestNzTableComponent] }); TestBed.compileComponents(); })); diff --git a/components/table/nz-thead.spec.ts b/components/table/nz-thead.spec.ts index 034da2177f6..209b3119e4a 100644 --- a/components/table/nz-thead.spec.ts +++ b/components/table/nz-thead.spec.ts @@ -1,7 +1,6 @@ import { Component, DebugElement } from '@angular/core'; import { fakeAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; -import { NzMeasureScrollbarService } from 'ng-zorro-antd/core'; import { NzIconTestModule } from 'ng-zorro-antd/icon/testing'; import { NzTableComponent } from './nz-table.component'; import { NzTableModule } from './nz-table.module'; @@ -10,8 +9,7 @@ describe('nz-thead', () => { beforeEach(fakeAsync(() => { TestBed.configureTestingModule({ imports: [NzTableModule, NzIconTestModule], - declarations: [NzTheadTestNzTableComponent], - providers: [NzMeasureScrollbarService] + declarations: [NzTheadTestNzTableComponent] }); TestBed.compileComponents(); })); diff --git a/components/table/nz-tr.spec.ts b/components/table/nz-tr.spec.ts index 9f348c73902..f2f0fada2b7 100644 --- a/components/table/nz-tr.spec.ts +++ b/components/table/nz-tr.spec.ts @@ -1,7 +1,6 @@ import { Component, DebugElement } from '@angular/core'; import { fakeAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; -import { NzMeasureScrollbarService } from 'ng-zorro-antd/core'; import { NzTableModule } from './nz-table.module'; import { NzTrDirective } from './nz-tr.directive'; @@ -9,8 +8,7 @@ describe('nz-tr', () => { beforeEach(fakeAsync(() => { TestBed.configureTestingModule({ imports: [NzTableModule], - declarations: [NzTrTestTableComponent, NzTrTestNzTableComponent], - providers: [NzMeasureScrollbarService] + declarations: [NzTrTestTableComponent, NzTrTestNzTableComponent] }); TestBed.compileComponents(); })); diff --git a/package.json b/package.json index 8dae196b616..e1a2bd8e75a 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "date-fns": "^1.30.1" }, "devDependencies": { - "@angular-devkit/build-angular": "0.800.3", + "@angular-devkit/build-angular": "^0.800.3", "@angular-devkit/build-ng-packagr": "^0.800.1", "@angular-devkit/core": "^8.0.1", "@angular-devkit/schematics": "^8.0.1",