user10391869
user10391869

Reputation: 241

react ag-grid auto size columns and grid width

I am using ag-grid, I want the columns width to be dynamic according to the grid content, I do it by using:

const onGridReady = params => {
    params.columnApi.autoSizeAllColumns();
};

but the width of the grid is alays fixed, I have a space in the side of the grid. (I can't also send width to the grid, because I can't know what will be the size of the content) what I need is something how to combine autoSizeAllColumns and sizeColumnsToFit functions.

Upvotes: 9

Views: 19613

Answers (3)

benny254
benny254

Reputation: 56

You can pass properties into the defaultColDef column as shown below.

  <AgGridReact
                    rowData={rowData}
                    columnDefs={colDefs}
                    onGridReady={onGridReady}
                    domLayout="autoHeight"
                    defaultColDef={{
                        // flex: 1,
                        minWidth: 150,
                        resizable: true,
                        sortable: true,
                        filter: true,
                        floatingFilter: true,
                        // wrapText: true,
                        autoHeight: true,
                        // cellStyle: { whiteSpace: 'normal' },
                    }}
                    singleClickEdit
                    rowSelection="multiple"
                    stopEditingWhenCellsLoseFocus={true}
                />

Upvotes: 0

SendETHToThisAddress
SendETHToThisAddress

Reputation: 3704

ag-grid has a property called defaultColDef that can be used for grid settings. If you pass flex: 1 as one of the parameters then all columns will size to fit so that you won't have that empty space on the side (expands to fill). Check out the ag-grid documentation on this page and search for the word "flex" for more details on auto/flex sizing.

Upvotes: 7

Borislav Borisov
Borislav Borisov

Reputation: 33

If I understand you correctly you want to have the following behaviour for resizing - make sure each column has it's content visible first, but then also make sure that the whole grid width is filled at the least.

Unfortunately there doesn't seem to be a really straightforward way to achieve that. What I did is onGridReady, I would use the autoSizeColumns function to make sure that each column's content is fully visible, and then if there is an additional space left to fill the grid's width I distribute it evenly to each column. Then apply the new column state through gridApi.applyColumnState. Here is an example in vue that should be fairly easy to transfer to other frameworks (or vanilla js).

interface UseGridColumnResizeOptions {
  // we need access to the grid container so we can calculate
  // the space that is left unfilled.
  gridContainerRef: Ref<null | HTMLElement>;
  // for any columns that you don't want to resize for whatever reason
  skipResizeColumnIds: string[];
}

export const useGridColumnResize = ({ gridContainerRef, skipResizeColumnIds }: UseGridColumnResizeOptions) => {
  const handleResize = ({ columnApi }: AgGridEvent) => {
    columnApi.autoSizeAllColumns();

    if (!gridContainerRef.value) {
      console.warn('Unable to resize columns, gridContainer ref is not provided');

      return;
    }

    const isColumnResizable = (colDef: ColDef) => colDef.resizable && !skipResizeColumnIds.includes(colDef.colId!);
    const columns = columnApi.getAllGridColumns().filter((column) => isColumnResizable(column.getColDef()));

    if (columns.length === 0) {
      return;
    }

    const lastColumn = columns[columns.length - 1];
    const lastColumnLeft = lastColumn.getLeft();
    const lastColumnWidth = lastColumn.getActualWidth();
    const { width: gridWidth } = gridContainerRef.value.getBoundingClientRect();
    const gridSpaceLeftToFill = Math.max(0, gridWidth - (lastColumnLeft! + lastColumnWidth));

    if (gridSpaceLeftToFill === 0) {
      return;
    }

    const additionalSpaceForEachColumn = gridSpaceLeftToFill / columns.length;
    const columnState = columnApi.getColumnState();

    columnState.forEach((column) => {
      const skipResizeForColumn = !columns.some((col) => col.getColId() === column.colId);

      if (skipResizeForColumn) {
        return;
      }

      column.width = column.width! + additionalSpaceForEachColumn;
    });

    columnApi.applyColumnState({ state: columnState });
  };

  return { handleResize };
};

You can plug the handleResize function on row-data-updated event to resize columns whenever new data arrives in the grid or only once in grid-ready or first-data-rendered.

Keep in mind that this implementation plays out well in my case as columns are not movable. I am expecting the last column inside the columns array to be the last visible one in the UI, but that might not always be the case and you might end up with wrong calculation of the space that is left to fill. So you might need to change the way the last visible column in the UI is retrieved to make it work for your case.

Upvotes: 1

Related Questions