diff --git a/packages/modules/data-widgets/src/themesource/datawidgets/web/_datagrid.scss b/packages/modules/data-widgets/src/themesource/datawidgets/web/_datagrid.scss index 8ca532f190..e72d3f0a9f 100644 --- a/packages/modules/data-widgets/src/themesource/datawidgets/web/_datagrid.scss +++ b/packages/modules/data-widgets/src/themesource/datawidgets/web/_datagrid.scss @@ -395,6 +395,11 @@ $root: ".widget-datagrid"; display: grid !important; min-width: fit-content; margin-bottom: 0; + &.infinite-loading { + // in order to restrict the scroll to row area + // we need to prevent table itself to expanding beyond available position + min-width: 0; + } } } @@ -530,24 +535,57 @@ $root: ".widget-datagrid"; margin: var(--spacing-small, 8px) 0; } -.infinite-loading.widget-datagrid-grid-body { - // when virtual scroll is enabled we make area that holds rows scrollable - // (while the area that holds column headers still stays in place) - overflow-y: auto; +.infinite-loading { + .widget-datagrid-grid-head { + width: calc(var(--widgets-grid-width) - var(--widgets-grid-scrollbar-size)); + overflow-x: hidden; + } + .widget-datagrid-grid-head[data-scrolled-y="true"] { + box-shadow: 0 5px 5px -5px gray; + } + + .widget-datagrid-grid-body { + width: var(--widgets-grid-width); + overflow-y: auto; + max-height: var(--widgets-grid-body-height); + } + + .widget-datagrid-grid-head[data-scrolled-x="true"]:after { + content: ""; + position: absolute; + left: 0px; + width: 10px; + box-shadow: inset 5px 0 5px -5px gray; + top: 0; + bottom: 0; + } } -.widget-datagrid-grid-head, +.widget-datagrid-grid-head { + display: grid; + + // this head is not part of the grid, so it has dedicated column template --widgets-grid-template-columns-head + // but it might not be available at the initial render, so we use template from the grid --widgets-grid-template-columns + // using template from the grid might to misalignment from the grid itself, + // but in practice: + // - grid has no data at that moment, so misalignment is not visible. + // - as soon as the grid itself gets rendered --widgets-grid-template-columns-head gets calculated + // and everything looks like it should. + grid-template-columns: var(--widgets-grid-template-columns-head, var(--widgets-grid-template-columns)); +} .widget-datagrid-grid-body { // this element has to position their children (columns or headers) // as grid and have those aligned with the parent grid display: grid; // this property makes sure we align our own grid columns // to the columns defined in the global grid - grid-template-columns: subgrid; + grid-template-columns: var(--widgets-grid-template-columns); +} - // ensure that we cover all columns of original top level grid - // so our own columns get aligned with the parent +.grid-mock-header { + grid-template-columns: subgrid; grid-column: 1 / -1; + display: grid; } :where(#{$root}-paging-bottom, #{$root}-padding-top) { diff --git a/packages/pluggableWidgets/datagrid-web/CHANGELOG.md b/packages/pluggableWidgets/datagrid-web/CHANGELOG.md index 1f7339aa51..721bfa9705 100644 --- a/packages/pluggableWidgets/datagrid-web/CHANGELOG.md +++ b/packages/pluggableWidgets/datagrid-web/CHANGELOG.md @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] +### Changed + +- We improved virtual scrolling behavior when horizontal scrolling is present due to grid size. + ### Added - We added a new property for export to excel. The new property allows to set the cell export type and also the format for type number and date. diff --git a/packages/pluggableWidgets/datagrid-web/src/components/Grid.tsx b/packages/pluggableWidgets/datagrid-web/src/components/Grid.tsx index 015fb3f539..9c3135bc33 100644 --- a/packages/pluggableWidgets/datagrid-web/src/components/Grid.tsx +++ b/packages/pluggableWidgets/datagrid-web/src/components/Grid.tsx @@ -1,16 +1,22 @@ +import classNames from "classnames"; import { observer } from "mobx-react-lite"; import { PropsWithChildren, ReactElement } from "react"; -import { useDatagridConfig, useGridStyle } from "../model/hooks/injection-hooks"; +import { useDatagridConfig, useGridSizeStore, useGridStyle } from "../model/hooks/injection-hooks"; export const Grid = observer(function Grid(props: PropsWithChildren): ReactElement { const config = useDatagridConfig(); + const gridSizeStore = useGridSizeStore(); + const style = useGridStyle().get(); return (
{props.children}
diff --git a/packages/pluggableWidgets/datagrid-web/src/components/GridBody.tsx b/packages/pluggableWidgets/datagrid-web/src/components/GridBody.tsx index a8ededee80..c27b6337c6 100644 --- a/packages/pluggableWidgets/datagrid-web/src/components/GridBody.tsx +++ b/packages/pluggableWidgets/datagrid-web/src/components/GridBody.tsx @@ -1,8 +1,8 @@ -import classNames from "classnames"; import { observer } from "mobx-react-lite"; import { Fragment, PropsWithChildren, ReactElement, ReactNode } from "react"; import { useDatagridConfig, + useGridSizeStore, useItemCount, useLoaderViewModel, usePaginationService, @@ -14,14 +14,14 @@ import { SpinnerLoader } from "./loader/SpinnerLoader"; export const GridBody = observer(function GridBody(props: PropsWithChildren): ReactElement { const { children } = props; - const { bodySize, containerRef, isInfinite, handleScroll } = useBodyScroll(); + const gridSizeStore = useGridSizeStore(); + const { handleScroll } = useBodyScroll(); return (
0 ? { maxHeight: `${bodySize}px` } : {}} + className={"widget-datagrid-grid-body table-content"} role="rowgroup" - ref={containerRef} + ref={gridSizeStore.gridBodyRef} onScroll={handleScroll} > {children} diff --git a/packages/pluggableWidgets/datagrid-web/src/components/GridHeader.tsx b/packages/pluggableWidgets/datagrid-web/src/components/GridHeader.tsx index 39b86c6d3a..a378cd42b7 100644 --- a/packages/pluggableWidgets/datagrid-web/src/components/GridHeader.tsx +++ b/packages/pluggableWidgets/datagrid-web/src/components/GridHeader.tsx @@ -1,5 +1,5 @@ import { ReactElement, useState } from "react"; -import { useColumnsStore, useDatagridConfig } from "../model/hooks/injection-hooks"; +import { useColumnsStore, useDatagridConfig, useGridSizeStore } from "../model/hooks/injection-hooks"; import { ColumnId } from "../typings/GridColumn"; import { CheckboxColumnHeader } from "./CheckboxColumnHeader"; import { ColumnProvider } from "./ColumnProvider"; @@ -11,6 +11,7 @@ import { HeaderSkeletonLoader } from "./loader/HeaderSkeletonLoader"; export function GridHeader(): ReactElement { const { columnsHidable, id: gridId } = useDatagridConfig(); const columnsStore = useColumnsStore(); + const gridSizeStore = useGridSizeStore(); const columns = columnsStore.visibleColumns; const [dragOver, setDragOver] = useState<[ColumnId, "before" | "after"] | undefined>(undefined); const [isDragging, setIsDragging] = useState<[ColumnId | undefined, ColumnId, ColumnId | undefined] | undefined>(); @@ -20,7 +21,7 @@ export function GridHeader(): ReactElement { } return ( -
+
{columns.map(column => ( diff --git a/packages/pluggableWidgets/datagrid-web/src/components/Header.tsx b/packages/pluggableWidgets/datagrid-web/src/components/Header.tsx index ed334d2ad9..1c396b3b75 100644 --- a/packages/pluggableWidgets/datagrid-web/src/components/Header.tsx +++ b/packages/pluggableWidgets/datagrid-web/src/components/Header.tsx @@ -60,7 +60,6 @@ export function Header(props: HeaderProps): ReactElement { role="columnheader" style={!canSort ? { cursor: "unset" } : undefined} title={caption} - ref={ref => column.setHeaderElementRef(ref)} data-column-id={column.columnId} onDrop={draggableProps.onDrop} onDragEnter={draggableProps.onDragEnter} diff --git a/packages/pluggableWidgets/datagrid-web/src/components/MockHeader.tsx b/packages/pluggableWidgets/datagrid-web/src/components/MockHeader.tsx new file mode 100644 index 0000000000..9035326a1a --- /dev/null +++ b/packages/pluggableWidgets/datagrid-web/src/components/MockHeader.tsx @@ -0,0 +1,56 @@ +import { ReactNode, useCallback, useEffect, useRef } from "react"; +import { useColumnsStore, useDatagridConfig, useGridSizeStore } from "../model/hooks/injection-hooks"; + +function getColumnSizes(container: HTMLDivElement | null): Map { + const sizes = new Map(); + if (container) { + container.querySelectorAll("[data-column-id]").forEach(c => { + const columnId = c.dataset.columnId; + if (!columnId) { + console.debug("getColumnSizes: can't find id on:", c); + return; + } + sizes.set(columnId, c.offsetWidth); + }); + } + + return sizes; +} + +export function MockHeader(): ReactNode { + const columnsStore = useColumnsStore(); + const config = useDatagridConfig(); + const gridSizeStore = useGridSizeStore(); + const headerRef = useRef(null); + const resizeCallback = useCallback(() => { + gridSizeStore.updateColumnSizes(getColumnSizes(headerRef.current).values().toArray()); + }, [headerRef, gridSizeStore]); + + useEffect(() => { + const observer = new ResizeObserver(resizeCallback); + + if (headerRef.current) { + observer.observe(headerRef.current); + } + return () => { + observer.disconnect(); + }; + }, [resizeCallback, headerRef]); + + return ( +
+ {config.checkboxColumnEnabled &&
} + {columnsStore.visibleColumns.map(c => ( +
c.setHeaderElementRef(ref)} + >
+ ))} + {config.selectorColumnEnabled &&
} +
+ ); +} diff --git a/packages/pluggableWidgets/datagrid-web/src/components/Widget.tsx b/packages/pluggableWidgets/datagrid-web/src/components/Widget.tsx index bce68e5755..9d11e7b5d7 100644 --- a/packages/pluggableWidgets/datagrid-web/src/components/Widget.tsx +++ b/packages/pluggableWidgets/datagrid-web/src/components/Widget.tsx @@ -13,6 +13,7 @@ import { WidgetFooter } from "./WidgetFooter"; import { WidgetHeader } from "./WidgetHeader"; import { WidgetRoot } from "./WidgetRoot"; import { WidgetTopBar } from "./WidgetTopBar"; +import { MockHeader } from "./MockHeader"; export function Widget(props: { onExportCancel?: () => void }): ReactElement { return ( @@ -25,6 +26,7 @@ export function Widget(props: { onExportCancel?: () => void }): ReactElement { + diff --git a/packages/pluggableWidgets/datagrid-web/src/components/__tests__/__snapshots__/Grid.spec.tsx.snap b/packages/pluggableWidgets/datagrid-web/src/components/__tests__/__snapshots__/Grid.spec.tsx.snap index a6e74b1f27..3751635dc2 100644 --- a/packages/pluggableWidgets/datagrid-web/src/components/__tests__/__snapshots__/Grid.spec.tsx.snap +++ b/packages/pluggableWidgets/datagrid-web/src/components/__tests__/__snapshots__/Grid.spec.tsx.snap @@ -5,7 +5,7 @@ exports[`Grid renders without crashing 1`] = `
Test
@@ -17,7 +17,7 @@ exports[`Grid renders without selector column 1`] = `
Test
diff --git a/packages/pluggableWidgets/datagrid-web/src/helpers/state/column/ColumnStore.tsx b/packages/pluggableWidgets/datagrid-web/src/helpers/state/column/ColumnStore.tsx index 7a48f5b404..9ee3cf83ee 100644 --- a/packages/pluggableWidgets/datagrid-web/src/helpers/state/column/ColumnStore.tsx +++ b/packages/pluggableWidgets/datagrid-web/src/helpers/state/column/ColumnStore.tsx @@ -28,6 +28,8 @@ export class ColumnStore implements GridColumn { private baseInfo: BaseColumnInfo; private parentStore: IColumnParentStore; + // this holds size of the column that it had prior to resizing started + // this is needed to prevent personalization being saved while resizing private frozenSize: number | undefined; // dynamic props from PW API diff --git a/packages/pluggableWidgets/datagrid-web/src/model/containers/Datagrid.container.ts b/packages/pluggableWidgets/datagrid-web/src/model/containers/Datagrid.container.ts index fd99730e77..172275ab3e 100644 --- a/packages/pluggableWidgets/datagrid-web/src/model/containers/Datagrid.container.ts +++ b/packages/pluggableWidgets/datagrid-web/src/model/containers/Datagrid.container.ts @@ -32,6 +32,7 @@ import { DerivedLoaderController } from "../services/DerivedLoaderController"; import { PaginationController } from "../services/PaginationController"; import { SelectionGate } from "../services/SelectionGate.service"; import { CORE_TOKENS as CORE, DG_TOKENS as DG, SA_TOKENS } from "../tokens"; +import { GridSizeStore } from "../stores/GridSize.store"; // base injected(ColumnGroupStore, CORE.setupService, CORE.mainGate, CORE.config, DG.filterHost); @@ -40,6 +41,7 @@ injected(DatasourceService, CORE.setupService, DG.queryGate, DG.refreshInterval. injected(PaginationController, CORE.setupService, DG.paginationConfig, DG.query); injected(GridBasicData, CORE.mainGate); injected(WidgetRootViewModel, CORE.mainGate, CORE.config, DG.exportProgressService, SA_TOKENS.selectionDialogVM); +injected(GridSizeStore, DG.paginationService); // loader injected(DerivedLoaderController, DG.query, DG.exportProgressService, CORE.columnsStore, DG.loaderConfig); @@ -58,7 +60,7 @@ injected(GridPersonalizationStore, CORE.setupService, CORE.mainGate, CORE.column // selection injected(SelectionGate, CORE.mainGate); injected(createSelectionHelper, CORE.setupService, DG.selectionGate, CORE.config.optional); -injected(gridStyleAtom, CORE.columnsStore, CORE.config); +injected(gridStyleAtom, CORE.columnsStore, CORE.config, DG.gridSizeStore); injected(rowClassProvider, CORE.mainGate); // row-interaction @@ -98,6 +100,8 @@ export class DatagridContainer extends Container { this.bind(DG.query).toInstance(DatasourceService).inSingletonScope(); // Pagination service this.bind(DG.paginationService).toInstance(PaginationController).inSingletonScope(); + // Grid sizing and scrolling store + this.bind(DG.gridSizeStore).toInstance(GridSizeStore).inSingletonScope(); // Datasource params service this.bind(DG.paramsService).toInstance(DatasourceParamsController).inSingletonScope(); // FilterAPI @@ -229,5 +233,7 @@ export class DatagridContainer extends Container { // Hydrate filters from props this.get(DG.combinedFilter).hydrate(props.datasource.filter); + + this.get(DG.gridSizeStore); } } diff --git a/packages/pluggableWidgets/datagrid-web/src/model/hooks/injection-hooks.ts b/packages/pluggableWidgets/datagrid-web/src/model/hooks/injection-hooks.ts index 337a03637f..77bf97a510 100644 --- a/packages/pluggableWidgets/datagrid-web/src/model/hooks/injection-hooks.ts +++ b/packages/pluggableWidgets/datagrid-web/src/model/hooks/injection-hooks.ts @@ -9,6 +9,7 @@ export const [useExportProgressService] = createInjectionHooks(DG.exportProgress export const [useLoaderViewModel] = createInjectionHooks(DG.loaderVM); export const [useMainGate] = createInjectionHooks(CORE.mainGate); export const [usePaginationService] = createInjectionHooks(DG.paginationService); +export const [useGridSizeStore] = createInjectionHooks(DG.gridSizeStore); export const [useSelectionHelper] = createInjectionHooks(DG.selectionHelper); export const [useGridStyle] = createInjectionHooks(DG.gridColumnsStyle); export const [useQueryService] = createInjectionHooks(DG.query); diff --git a/packages/pluggableWidgets/datagrid-web/src/model/hooks/useBodyScroll.ts b/packages/pluggableWidgets/datagrid-web/src/model/hooks/useBodyScroll.ts index e5fd2eed3a..eb98f0e965 100644 --- a/packages/pluggableWidgets/datagrid-web/src/model/hooks/useBodyScroll.ts +++ b/packages/pluggableWidgets/datagrid-web/src/model/hooks/useBodyScroll.ts @@ -1,27 +1,12 @@ -import { useInfiniteControl } from "@mendix/widget-plugin-grid/components/InfiniteBody"; -import { RefObject, UIEventHandler, useCallback } from "react"; -import { usePaginationService } from "./injection-hooks"; +import { UIEventHandler } from "react"; +import { useInfiniteControl } from "./useInfiniteControl"; export function useBodyScroll(): { handleScroll: UIEventHandler | undefined; - bodySize: number; - containerRef: RefObject; - isInfinite: boolean; } { - const paging = usePaginationService(); - const setPage = useCallback((cb: (n: number) => number) => paging.setPage(cb), [paging]); - - const isInfinite = paging.pagination === "virtualScrolling"; - const [trackScrolling, bodySize, containerRef] = useInfiniteControl({ - hasMoreItems: paging.hasMoreItems, - isInfinite, - setPage - }); + const [trackBodyScrolling] = useInfiniteControl(); return { - handleScroll: isInfinite ? trackScrolling : undefined, - bodySize, - containerRef, - isInfinite + handleScroll: trackBodyScrolling }; } diff --git a/packages/pluggableWidgets/datagrid-web/src/model/hooks/useInfiniteControl.tsx b/packages/pluggableWidgets/datagrid-web/src/model/hooks/useInfiniteControl.tsx new file mode 100644 index 0000000000..c9f7fa9b8d --- /dev/null +++ b/packages/pluggableWidgets/datagrid-web/src/model/hooks/useInfiniteControl.tsx @@ -0,0 +1,66 @@ +import { RefObject, UIEvent, useCallback, useEffect, useLayoutEffect } from "react"; +import { useOnScreen } from "@mendix/widget-plugin-hooks/useOnScreen"; +import { useGridSizeStore } from "@mendix/datagrid-web/src/model/hooks/injection-hooks"; +import { VIRTUAL_SCROLLING_OFFSET } from "../stores/GridSize.store"; + +export function useInfiniteControl(): [trackBodyScrolling: ((e: any) => void) | undefined] { + const gridSizeStore = useGridSizeStore(); + + const isVisible = useOnScreen(gridSizeStore.gridBodyRef as RefObject); + + const trackBodyScrolling = useCallback( + (e: UIEvent) => { + const target = e.target as HTMLElement; + const head = gridSizeStore.gridHeaderRef.current; + if (head) { + // synchronize header position to the body as they are decoupled + // we don't use state to optimize speed as we + // don't want a re-render. + head.scrollTo({ left: target.scrollLeft }); + + // this is cosmetic, needed to provide nice shadows when body is scrolled + head.dataset.scrolledY = target.scrollTop > 0 ? "true" : "false"; + head.dataset.scrolledX = target.scrollLeft > 0 ? "true" : "false"; + } + + // we need to determine scrollbar width to calculate header size correctly in css + gridSizeStore.setScrollBarSize(target.offsetWidth - target.clientWidth); + + /** + * In Windows OS the result of first expression returns a non integer and result in never loading more, require floor to solve. + * note: Math floor sometimes result in incorrect integer value, + * causing mismatch by 1 pixel point, thus, add magic number 2 as buffer. + */ + const bottom = + Math.floor(target.scrollHeight - VIRTUAL_SCROLLING_OFFSET - target.scrollTop) <= + Math.floor(target.clientHeight) + 2; + if (bottom) { + gridSizeStore.bumpPage(); + } + }, + [gridSizeStore] + ); + + useEffect(() => { + setTimeout(() => isVisible && gridSizeStore.lockGridBodyHeight(), 100); + }, [isVisible, gridSizeStore]); + + useLayoutEffect(() => { + const observeTarget = gridSizeStore.gridContainerRef.current; + if (!gridSizeStore.hasVirtualScrolling || !observeTarget) return; + + const resizeObserver = new ResizeObserver(entries => { + for (const entry of entries) { + gridSizeStore.setGridWidth(entry.target.clientWidth ? entry.target.clientWidth : undefined); + } + }); + + resizeObserver.observe(observeTarget); + + return () => { + resizeObserver.unobserve(observeTarget); + }; + }, [gridSizeStore]); + + return [gridSizeStore.hasVirtualScrolling ? trackBodyScrolling : undefined]; +} diff --git a/packages/pluggableWidgets/datagrid-web/src/model/models/grid.model.ts b/packages/pluggableWidgets/datagrid-web/src/model/models/grid.model.ts index 559b2bf366..e8c99f06a3 100644 --- a/packages/pluggableWidgets/datagrid-web/src/model/models/grid.model.ts +++ b/packages/pluggableWidgets/datagrid-web/src/model/models/grid.model.ts @@ -3,23 +3,44 @@ import { computed } from "mobx"; import { CSSProperties } from "react"; import { ColumnGroupStore } from "../../helpers/state/ColumnGroupStore"; import { DatagridConfig } from "../configs/Datagrid.config"; +import { GridColumn } from "../../typings/GridColumn"; +import { GridSizeStore } from "../stores/GridSize.store"; -export function gridStyleAtom(columns: ColumnGroupStore, config: DatagridConfig): ComputedAtom { - return computed(() => { - return gridStyle(columns.visibleColumns, { - checkboxColumn: config.checkboxColumnEnabled, - selectorColumn: config.selectorColumnEnabled - }); - }); +export function gridStyleAtom( + columns: ColumnGroupStore, + config: DatagridConfig, + gridSizeStore: GridSizeStore +): ComputedAtom { + return computed( + () => + ({ + "--widgets-grid-template-columns": templateColumns(columns.visibleColumns, { + checkboxColumn: config.checkboxColumnEnabled, + selectorColumn: config.selectorColumnEnabled + }), + "--widgets-grid-template-columns-head": gridSizeStore.templateColumnsHead, + "--widgets-grid-body-height": asPx(gridSizeStore.gridBodyHeight), + "--widgets-grid-width": asPx(gridSizeStore.gridWidth), + "--widgets-grid-scrollbar-size": asPx(gridSizeStore.scrollBarSize) + }) as CSSProperties + ); } -function gridStyle( - columns: Array<{ getCssWidth(): string }>, +function asPx(v: number | undefined): string | undefined { + if (v === undefined) { + return undefined; + } + + return `${v}px`; +} + +function templateColumns( + columns: GridColumn[], optional: { - checkboxColumn?: boolean; - selectorColumn?: boolean; + checkboxColumn: boolean; + selectorColumn: boolean; } -): CSSProperties { +): string { const columnSizes = columns.map(c => c.getCssWidth()); const sizes: string[] = []; @@ -34,7 +55,5 @@ function gridStyle( sizes.push("54px"); } - return { - gridTemplateColumns: sizes.join(" ") - }; + return sizes.join(" "); } diff --git a/packages/pluggableWidgets/datagrid-web/src/model/stores/GridSize.store.ts b/packages/pluggableWidgets/datagrid-web/src/model/stores/GridSize.store.ts new file mode 100644 index 0000000000..fee206c8df --- /dev/null +++ b/packages/pluggableWidgets/datagrid-web/src/model/stores/GridSize.store.ts @@ -0,0 +1,80 @@ +import { action, computed, makeAutoObservable, observable } from "mobx"; +import { createRef } from "react"; +import { PaginationController } from "../services/PaginationController"; + +export const VIRTUAL_SCROLLING_OFFSET = 30; + +export class GridSizeStore { + gridContainerRef = createRef(); + gridBodyRef = createRef(); + gridHeaderRef = createRef(); + + scrollBarSize?: number; + gridWidth?: number; + gridBodyHeight?: number; + columnSizes?: number[]; + + paging: PaginationController; + + constructor(paging: PaginationController) { + this.paging = paging; + + makeAutoObservable(this, { + gridContainerRef: false, + gridBodyRef: false, + gridHeaderRef: false, + + scrollBarSize: observable, + setScrollBarSize: action, + + gridWidth: observable, + setGridWidth: action, + + gridBodyHeight: observable, + lockGridBodyHeight: action, + + columnSizes: observable, + updateColumnSizes: action, + + templateColumnsHead: computed + }); + } + + get hasVirtualScrolling(): boolean { + return this.paging.pagination === "virtualScrolling"; + } + + get templateColumnsHead(): string | undefined { + return this.columnSizes?.map(s => `${s}px`).join(" "); + } + + bumpPage(): void { + if (this.paging.hasMoreItems) { + return this.paging.setPage(page => page + 1); + } + } + + setScrollBarSize(size: number): void { + this.scrollBarSize = size; + } + + setGridWidth(size: number | undefined): void { + this.gridWidth = size; + } + + updateColumnSizes(sizes: number[]): void { + this.columnSizes = sizes; + } + + lockGridBodyHeight(): void { + if (!this.hasVirtualScrolling || !this.paging.hasMoreItems) { + return; + } + const gridBody = this.gridBodyRef.current; + if (!gridBody || this.gridBodyHeight !== undefined) { + return; + } + + this.gridBodyHeight = gridBody.clientHeight - VIRTUAL_SCROLLING_OFFSET; + } +} diff --git a/packages/pluggableWidgets/datagrid-web/src/model/tokens.ts b/packages/pluggableWidgets/datagrid-web/src/model/tokens.ts index 26b3e38201..b9ffd203c9 100644 --- a/packages/pluggableWidgets/datagrid-web/src/model/tokens.ts +++ b/packages/pluggableWidgets/datagrid-web/src/model/tokens.ts @@ -42,6 +42,7 @@ import { DerivedLoaderController, DerivedLoaderControllerConfig } from "./servic import { PaginationConfig, PaginationController } from "./services/PaginationController"; import { TextsService } from "./services/Texts.service"; import { PageSizeStore } from "./stores/PageSize.store"; +import { GridSizeStore } from "./stores/GridSize.store"; /** Tokens to resolve dependencies from the container. */ @@ -104,6 +105,8 @@ export const DG_TOKENS = { paginationConfig: token("PaginationConfig"), paginationService: token("PaginationService"), + gridSizeStore: token("@store:GridSizeStore"), + parentChannelName: token("parentChannelName"), refreshInterval: token("refreshInterval"),