clr-angular-static-fix
Version:
1. Install Clarity Icons package through npm:
196 lines (172 loc) • 6.86 kB
text/typescript
/*
* Copyright (c) 2016-2018 VMware, Inc. All Rights Reserved.
* This software is released under MIT license.
* The full license information can be found in LICENSE in the root directory of this project.
*/
import { isPlatformBrowser } from '@angular/common';
import {
AfterContentInit,
AfterViewChecked,
ContentChildren,
Directive,
ElementRef,
OnDestroy,
PLATFORM_ID,
QueryList,
Renderer2,
} from '@angular/core';
import { Subscription } from 'rxjs';
import { Items } from '../providers/items';
import { Page } from '../providers/page';
import { DomAdapter } from './dom-adapter';
import { DatagridHeaderRenderer } from './header-renderer';
import { NoopDomAdapter } from './noop-dom-adapter';
import { DatagridRenderOrganizer } from './render-organizer';
// Fixes build error
// @dynamic (https://github.com/angular/angular/issues/19698#issuecomment-338340211)
export const domAdapterFactory = (platformId: Object) => {
if (isPlatformBrowser(platformId)) {
return new DomAdapter();
} else {
return new NoopDomAdapter();
}
};
// Fixes build error
// @dynamic (https://github.com/angular/angular/issues/19698#issuecomment-338340211)
export class DatagridMainRenderer implements AfterContentInit, AfterViewChecked, OnDestroy {
constructor(
private organizer: DatagridRenderOrganizer,
private items: Items,
private page: Page,
private domAdapter: DomAdapter,
private el: ElementRef,
private renderer: Renderer2
) {
this._subscriptions.push(organizer.computeWidths.subscribe(() => this.computeHeadersWidth()));
this._subscriptions.push(
this.page.sizeChange.subscribe(() => {
if (this._heightSet) {
this.resetDatagridHeight();
}
})
);
this._subscriptions.push(this.items.change.subscribe(() => (this.shouldStabilizeColumns = true)));
}
public headers: QueryList<DatagridHeaderRenderer>;
ngAfterContentInit() {
this._subscriptions.push(
this.headers.changes.subscribe(() => {
// TODO: only re-stabilize if a column was added or removed. Reordering is fine.
this.columnsSizesStable = false;
this.stabilizeColumns();
})
);
}
ngAfterViewChecked() {
if (this.shouldStabilizeColumns) {
this.stabilizeColumns();
}
if (this.shouldComputeHeight()) {
setTimeout(() => {
this.computeDatagridHeight();
});
}
}
private _heightSet: boolean = false;
private shouldComputeHeight(): boolean {
if (!this._heightSet && this.page.size > 0) {
if (this.items.displayed.length === this.page.size) {
return true;
}
}
return false;
}
/**
* Computes the height of the datagrid.
*
* NOTE: We had to choose to set the height instead of the min-height because
* IE 11 requires the height on the parent for the children flex grow/shrink properties to work.
* When we used min-height, 1 1 auto doesn't used to work in IE11 :-(
* But this doesn't affect the fix. It works in both fixed & variable height datagrids.
*
* Refer: http://stackoverflow.com/questions/24396205/flex-grow-not-working-in-internet-explorer-11-0
*/
private computeDatagridHeight() {
// IE doesn't return correct value for getComputedStyle(element).getPropertyValue("height")
const value: number = this.domAdapter.clientRectHeight(this.el.nativeElement);
this.renderer.setStyle(this.el.nativeElement, 'height', value + 'px');
this._heightSet = true;
}
private resetDatagridHeight() {
this.renderer.setStyle(this.el.nativeElement, 'height', '');
this._heightSet = false;
}
private _subscriptions: Subscription[] = [];
ngOnDestroy() {
this._subscriptions.forEach(sub => sub.unsubscribe());
}
/**
* Makes each header compute its width.
*/
private computeHeadersWidth() {
const nbColumns: number = this.headers.length;
let allStrict = true;
this.headers.forEach((header, index) => {
// On the last header column check whether all columns have strict widths.
// If all columns have strict widths, remove the strict width from the last column and make it the column's
// minimum width so that when all previous columns shrink, it will get a flexible width and cover the empty
// gap in the Datagrid.
if (!header.strictWidth) {
allStrict = false;
}
if (nbColumns === index + 1 && allStrict) {
delete header.strictWidth;
}
this.organizer.widths[index] = { px: header.computeWidth(), strict: !!header.strictWidth };
});
this.headers.forEach((header, index) => header.setWidth(this.organizer.widths[index].px));
}
/**
* Indicates if we want to re-compute columns width. This should only happen:
* 1) When headers change, with columns being added or removed
* 2) When rows are lazily loaded for the first time
*/
private columnsSizesStable = false;
private shouldStabilizeColumns = true;
/**
* Triggers a whole re-rendring cycle to set column sizes, if needed.
*/
private stabilizeColumns() {
this.shouldStabilizeColumns = false;
if (this.columnsSizesStable) {
// change in items might have introduced/taken away the scrollbar
// FIXME: setTimeout is needed here because:
// When the user changes the page the following things happen:
// 1. The array which contains the items displayed is updated to contain the items on the new page.
// 2. An event is emitted which is subscribed to by the main renderer (this file) and this marks the
// shouldStabilizeColumns flag to true
// 3. While this is happening the datagrid is in the process of cleaning up the view. The view first
// renders the new displayed items and then cleans up the old items. But there is a point where the view
// contains the old items as well as the new items. So if the page size is 10 the view contains 20 items.
// This causes the datagrid body to overflow.
// Now since shouldStabilizeColumns was set to true, the scrollbar width is calculated
// and added to the datagrid header. Adding the setTimeout gives Angular time to clean up the view so that
// the scrollbar disappears.
// See this: https://github.com/angular/angular/issues/19094
// When the above issue is resolve, remove the setTimeout
setTimeout(() => {
this.organizer.scrollbar.next();
});
return;
}
// No point resizing if there are no rows, we wait until they are actually loaded.
if (this.items.displayed.length > 0) {
this.organizer.resize();
this.columnsSizesStable = true;
}
}
}