Skip to content

Commit

Permalink
feat: Autosize when grid has rendered rows (#397)
Browse files Browse the repository at this point in the history
* Autosize when grid has rendered rows and rowData is not null
  • Loading branch information
matttdawson authored Sep 12, 2023
1 parent 7c6dd7f commit 6bcc810
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 29 deletions.
49 changes: 22 additions & 27 deletions src/components/Grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,13 @@ export const Grid = ({
selectColumnPinned = null,
contextMenuSelectRow = false,
singleClickEdit = false,
rowData,
rowHeight = theme === "ag-theme-step-default" ? 40 : theme === "ag-theme-step-compact" ? 36 : undefined,
...params
}: GridProps): ReactElement => {
const {
gridReady,
gridRenderState,
setApis,
ensureRowVisible,
getFirstRowId,
Expand Down Expand Up @@ -153,36 +155,38 @@ export const Grid = ({
*/
const hasSetContentSize = useRef(false);
const hasSetContentSizeEmpty = useRef(false);
const needsAutoSize = useRef(false);
const needsAutoSize = useRef(true);

const setInitialContentSize = useCallback(() => {
if (!gridDivRef.current?.clientWidth) {
if (!gridDivRef.current?.clientWidth || rowData == null) {
// Don't resize grids if they are offscreen as it doesn't work.
needsAutoSize.current = true;
return;
}

const headerCellCount = gridDivRef.current?.getElementsByClassName("ag-header-cell-label")?.length;
if (headerCellCount < 2) {
// Don't resize grids until all the columns are visible
// as `autoSizeColumns` will fail silently in this case
const gridRendered = gridRenderState();
if (gridRendered === null) {
// Don't resize until grid has rendered, or it has 0 rows.
needsAutoSize.current = true;
return;
}

const skipHeader = sizeColumns === "auto-skip-headers" && !isEmpty(params.rowData);
const skipHeader = sizeColumns === "auto-skip-headers" && gridRendered === "rows-visible";
if (sizeColumns === "auto" || skipHeader) {
const result = autoSizeColumns({ skipHeader, userSizedColIds: userSizedColIds.current, includeFlex: true });
if (isEmpty(params.rowData)) {
if (gridRendered === "empty") {
if (!hasSetContentSizeEmpty.current && result && !hasSetContentSize.current) {
hasSetContentSizeEmpty.current = true;
params.onContentSize && params.onContentSize(result);
}
} else {
} else if (gridRendered === "rows-visible") {
if (result && !hasSetContentSize.current) {
hasSetContentSize.current = true;
params.onContentSize && params.onContentSize(result);
}
} else {
// It should be impossible to get here
console.error("Unknown value returned from hasGridRendered");
}
}

Expand All @@ -191,7 +195,7 @@ export const Grid = ({
}
setAutoSized(true);
needsAutoSize.current = false;
}, [autoSizeColumns, params, sizeColumns, sizeColumnsToFit]);
}, [autoSizeColumns, gridRenderState, params, rowData, sizeColumns, sizeColumnsToFit]);

const lastOwnerDocumentRef = useRef<Document>();

Expand All @@ -213,25 +217,17 @@ export const Grid = ({
setInitialContentSize();
}
},
timeoutMs: 1000,
timeoutMs: 200,
});

const previousGridReady = useRef(gridReady);
useEffect(() => {
if (!previousGridReady.current && gridReady) {
previousGridReady.current = true;
setInitialContentSize();
}
}, [gridReady, setInitialContentSize]);

/**
* On data load select the first row of the grid if required.
*/
const hasSelectedFirstItem = useRef(false);
useEffect(() => {
if (!gridReady || hasSelectedFirstItem.current || !params.rowData || !externallySelectedItemsAreInSync) return;
if (!gridReady || hasSelectedFirstItem.current || !rowData || !externallySelectedItemsAreInSync) return;
hasSelectedFirstItem.current = true;
if (isNotEmpty(params.rowData) && isEmpty(params.externalSelectedItems)) {
if (isNotEmpty(rowData) && isEmpty(params.externalSelectedItems)) {
const firstRowId = getFirstRowId();
if (params.autoSelectFirstRow) {
selectRowsById([firstRowId]);
Expand All @@ -245,7 +241,7 @@ export const Grid = ({
gridReady,
params.externalSelectedItems,
params.autoSelectFirstRow,
params.rowData,
rowData,
selectRowsById,
getFirstRowId,
]);
Expand Down Expand Up @@ -402,7 +398,7 @@ export const Grid = ({
const previousRowDataLength = useRef(0);

const onRowDataChanged = useCallback(() => {
const length = params.rowData?.length ?? 0;
const length = rowData?.length ?? 0;
if (previousRowDataLength.current !== length) {
setInitialContentSize();
previousRowDataLength.current = length;
Expand All @@ -417,7 +413,7 @@ export const Grid = ({
const skipHeader = sizeColumns === "auto-skip-headers";
autoSizeColumns({ skipHeader, userSizedColIds: userSizedColIds.current, colIds: colIdsEdited.current });
colIdsEdited.current.clear();
}, [autoSizeColumns, params.rowData?.length, setInitialContentSize, sizeColumns, updatedDep, updatingCols]);
}, [autoSizeColumns, rowData?.length, setInitialContentSize, sizeColumns, updatedDep, updatingCols]);

/**
* Show/hide no rows overlay when model changes.
Expand Down Expand Up @@ -619,7 +615,6 @@ export const Grid = ({

//we don't want to show the row highlight if it wouldn't result in the row moving
const targetIndex = event.overIndex + position - (event.node.rowIndex < event.overIndex ? 1 : 0);
//console.log(targetIndex)
if (event.node.rowIndex != targetIndex) {
clientSideRowModel.highlightRowAtPixel(event.node as RowNode<any>, event.y);
}
Expand Down Expand Up @@ -663,7 +658,7 @@ export const Grid = ({
theme,
"theme-specific",
staleGrid && "Grid-sortIsStale",
gridReady && params.rowData && autoSized && "Grid-ready",
gridReady && rowData && autoSized && "Grid-ready",
)}
>
{gridContextMenu.component}
Expand Down Expand Up @@ -691,7 +686,7 @@ export const Grid = ({
onColumnResized={onColumnResized}
defaultColDef={{ minWidth: 48, ...omit(params.defaultColDef, ["editable"]) }}
columnDefs={columnDefsAdjusted}
rowData={params.rowData}
rowData={rowData}
noRowsOverlayComponent={(event: AgGridEvent) => {
let rowCount = 0;
event.api.forEachNode(() => rowCount++);
Expand Down
2 changes: 2 additions & 0 deletions src/contexts/GridContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export type AutoSizeColumnsResult = { width: number } | null;

export interface GridContextType<RowType extends GridBaseRow> {
gridReady: boolean;
gridRenderState: () => null | "empty" | "rows-visible";
getColDef: (colId?: string) => ColDef | undefined;
getColumns: (
filter?: keyof ColDef | ((r: ColDef) => boolean | undefined | null | number | string),
Expand Down Expand Up @@ -68,6 +69,7 @@ export interface GridContextType<RowType extends GridBaseRow> {

export const GridContext = createContext<GridContextType<any>>({
gridReady: false,
gridRenderState: () => null,
getColDef: () => {
console.error("no context provider for getColDef");
return undefined;
Expand Down
12 changes: 12 additions & 0 deletions src/contexts/GridContextProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,17 @@ export const GridContextProvider = <RowType extends GridBaseRow>(props: PropsWit
[quickFilter],
);

/**
* Used to check if it's OK to autosize.
*/
const gridRenderState = useCallback((): null | "empty" | "rows-visible" => {
if (!gridApi) return null;
if (!gridApi.getModel().isRowsToRender()) return "empty";
if (!isEmpty(gridApi.getRenderedNodes())) return "rows-visible";
// If there are rows to render, but there are no rendered nodes then we should wait
return null;
}, [gridApi]);

/**
* Expose scrollRowIntoView for playwright tests.
*/
Expand Down Expand Up @@ -701,6 +712,7 @@ export const GridContextProvider = <RowType extends GridBaseRow>(props: PropsWit
return (
<GridContext.Provider
value={{
gridRenderState,
getColDef,
getColumns,
getColumnIds,
Expand Down
4 changes: 2 additions & 2 deletions src/stories/grid/GridReadOnly.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ interface ITestRow {
id: number;
position: string;
age: number;
height: number;
height: string;
desc: string;
dd: string;
}
Expand Down Expand Up @@ -215,7 +215,7 @@ const GridReadOnlyTemplate: ComponentStory<typeof Grid> = (props: GridProps) =>
{ id: 1000, position: "Tester", age: 30, height: `6'4"`, desc: "Tests application", dd: "1" },
{ id: 1001, position: "Developer", age: 12, height: `5'3"`, desc: "Develops application", dd: "2" },
{ id: 1002, position: "Manager", age: 65, height: `5'9"`, desc: "Manages", dd: "3" },
]);
] as ITestRow[]);

return (
<GridWrapper maxHeight={300}>
Expand Down

0 comments on commit 6bcc810

Please sign in to comment.