'Ag-Grid: How to save and reload column order

Using Ag-Grid, users can drag columns to order them the way they like. I need to allow the user to save their column order (to an SQL backend) so that it becomes the default column order for them. I was trying to get the column names like this:

var cols = schedGridOptions.columnApi.getAllColumns();
for (col in cols) {
    var colDef = col.getColDef();
    console.log(colDef.headerName);
}

This was an example I found for setting the header name, so I tried to adapt it to getting the header name. But I get this error:

JavaScript runtime error: Object doesn't support property or method 'getColDef'

Perhaps I'm not doing this correctly? I'm fairly new at using Ag-Grid. Looking for suggestions.



Solution 1:[1]

You are looking for setColumnState() and getColumnState(). See the docs at https://www.ag-grid.com/javascript-grid-column-api/

In your grid options, set up event handlers for gridReady and columnMoved. https://www.ag-grid.com/javascript-grid-events/

Something like:

gridOptions = {
   rowData: myRowDataSource,
   columnDefs: myColumns,
   onGridReady: onGridReady,
   onColumnMoved: onColumnMoved,
}

On the column moved event, save the columnState. Here's an example saved to local storage. Change it to save to your database.

onColumnMoved(params) {
  var columnState = JSON.stringify(params.columnApi.getColumnState());
  localStorage.setItem('myColumnState', columnState);
}

On the grid ready event, get and restore the grid State. Again, change this to pull from your database.

onGridReady(params) {
    var columnState = JSON.parse(localStorage.getItem('myColumnState'));
    if (columnState) {
      params.columnApi.setColumnState(columnState);
    }
}

Solution 2:[2]

onColumnMoved will fire every time the column is moving but the drag didn't stopped.

Using onColumnMoved is not performant at all.

If you care about performance you should use onDragStopped

gridOptions.onDragStopped = function (params) {
  const colIds = params.columnApi.getAllDisplayedColumns().map(col => col.colId)
  console.log(colIds) // all visible colIds with the visible order
}

Solution 3:[3]

My answer is a small improvement of @roli's answer. The event will only be fired if the column order has been changed after the operation. If the user drags and decides to stop and drops the column at the same index as before, the event will not be fired.

enter image description here

The code below is the implementation in react. The idea is simple: Store the column order as a list of colId when the drag started and compare it to the final column order when the drag stopped. The event will only be fired when there is a different between the 2 order.

function useDragColumnChange(cb: (e: DragStoppedEvent) => void) {
  const columnOrderRef = React.useRef<string[]>([])
  const onDragStarted = (e: DragStartedEvent) => {
    columnOrderRef.current = e.columnApi.getColumnState().map(c => c.colId);
  }
  const onDragStopped = (e: DragStoppedEvent) => {
    const newColumnOrder = e.columnApi.getColumnState().map(c => c.colId);
    const sameOrder = columnOrderRef.current.every(
      (c, i) => c === newColumnOrder[i]
    );

    if (!sameOrder) {
      cb(e);
    }
  }

  return { onDragStarted, onDragStopped };
}

Usage

// in render()

const { onDragStarted, onDragStopped } = useDragColumnChange(e => console.log('Saving new column order!'))

return (
  <AgGridReact
    ...
    onDragStarted={onDragStarted}
    onDragStopped={onDragStopped}
  />
);

Live Demo

Edit Column Reorder Event

Solution 4:[4]

 gridOptions: GridOptions ={
  onDragStopped:(
    event: DragStoppedEvent  
  ) =>  this.test(event)  
  }
  
  test(params){
let columnDragState = params.columnApi.getColumnState();
console.log(columnDragState, "columnDragState")
const colIds = params.columnApi.getAllDisplayedColumns().map(e=>{
  return e.colDef
});
console.log(colIds)

  let arr3 = colIds.map((item, i) => Object.assign({}, item, columnDragState[i]));
  console.log(arr3)
}
<ag-grid-angular
    style="width: 1500px; height: 750px; padding-top: 10px;"
    class="ag-theme-alpine"
    [columnDefs]="columnDefs"
    (gridReady)="onGridReady($event)"
    [rowDragManaged]="true"
    
    [gridOptions]="gridOptions"
    [rowData]="rowData"
>
</ag-grid-angular>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Alien Technology
Solution 2 Roland
Solution 3
Solution 4