UNPKG

ag-grid

Version:

Advanced Data Grid / Data Table supporting Javascript / React / AngularJS / Web Components

136 lines (109 loc) 5.23 kB
import {Utils as _} from "../utils"; import {Autowired, PostConstruct} from "../context/context"; import {GridOptionsWrapper} from "../gridOptionsWrapper"; export interface RowContainerComponentParams { eContainer: HTMLElement; eViewport?: HTMLElement; hideWhenNoChildren?: boolean; } /** * There are many instances of this component covering each of the areas a row can be entered * eg body, pinned left, fullWidth. The component differs from others in that it's given the * elements, there is no template. All of the elements are part of the GridPanel. */ export class RowContainerComponent { @Autowired('gridOptionsWrapper') gridOptionsWrapper: GridOptionsWrapper; private readonly eContainer: HTMLElement; private readonly eViewport: HTMLElement; // full width containers only show when no children, because they float above the normal rows, // it adds complexity that can be confusing when inspecting the dom when they are not needed. private readonly hideWhenNoChildren: boolean; private childCount = 0; private visible: boolean; private rowTemplatesToAdd: string[] = []; private afterGuiAttachedCallbacks: Function[] = []; private scrollTop: number; // we ensure the rows are in the dom in the order in which they appear on screen when the // user requests this via gridOptions.ensureDomOrder. this is typically used for screen readers. private domOrder: boolean; private lastPlacedElement: HTMLElement; constructor(params: RowContainerComponentParams) { this.eContainer = params.eContainer; this.eViewport = params.eViewport; this.hideWhenNoChildren = params.hideWhenNoChildren; } public setVerticalScrollPosition(verticalScrollPosition: number): void { this.scrollTop = verticalScrollPosition; } @PostConstruct private postConstruct(): void { this.domOrder = this.gridOptionsWrapper.isEnsureDomOrder(); this.checkVisibility(); } public getRowElement(compId: number): HTMLElement { return <HTMLElement> this.eContainer.querySelector(`[comp-id="${compId}"]`); } public setHeight(height: number): void { this.eContainer.style.height = height + "px"; } public flushRowTemplates(): void { // if doing dom order, then rowTemplates will be empty, // or if no rows added since last time also empty. if (this.rowTemplatesToAdd.length!==0) { let htmlToAdd = this.rowTemplatesToAdd.join(''); _.appendHtml(this.eContainer, htmlToAdd); this.rowTemplatesToAdd.length = 0; } // this only empty if no rows since last time, as when // doing dom order, we still have callbacks to process this.afterGuiAttachedCallbacks.forEach( func => func() ); this.afterGuiAttachedCallbacks.length = 0; this.lastPlacedElement = null; } public appendRowTemplate(rowTemplate: string, callback: ()=>void) { if (this.domOrder) { this.lastPlacedElement = _.insertTemplateWithDomOrder(this.eContainer, rowTemplate, this.lastPlacedElement); } else { this.rowTemplatesToAdd.push(rowTemplate); } this.afterGuiAttachedCallbacks.push(callback); // it is important we put items in in order, so that when we open a row group, // the new rows are inserted after the opened group, but before the rows below. // that way, the rows below are over the new rows (as dom renders last in dom over // items previous in dom), otherwise the child rows would cover the row below and // that meant the user doesn't see the rows below slide away. this.childCount++; this.checkVisibility(); } public ensureDomOrder(eRow: HTMLElement): void { if (this.domOrder) { _.ensureDomOrder(this.eContainer, eRow, this.lastPlacedElement); this.lastPlacedElement = eRow; } } public removeRowElement(eRow: HTMLElement): void { this.eContainer.removeChild(eRow); this.childCount--; this.checkVisibility(); } private checkVisibility(): void { if (!this.hideWhenNoChildren) { return; } let eGui = this.eViewport ? this.eViewport : this.eContainer; let visible = this.childCount > 0; if (this.visible !== visible) { this.visible = visible; _.setVisible(eGui, visible); // if we are showing the viewport, then the scroll is always zero, // so we need to align with the other sections (ie if this is full // width container, and first time showing a full width row, we need to // scroll it so full width rows are show in right place alongside the // body rows). without this, there was an issue with 'loading rows' for // server side row model, as loading rows are full width, and they were // not getting displayed in the right location when rows were expanded. if (visible && this.eViewport) { this.eViewport.scrollTop = this.scrollTop; } } } }