tolsen64
tolsen64

Reputation: 999

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.

Upvotes: 23

Views: 38804

Answers (5)

Alien Technology
Alien Technology

Reputation: 1868

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.applyColumnState({state:columnState, applyOrder:true});
    }
}

Updated answer based on comments from @Sebastian and @jsN00b.

Upvotes: 41

KARTHIKEYAN.A
KARTHIKEYAN.A

Reputation: 20108

In the following way we can update the column orders manually using onColumnMoved or onDragStopped event

const onDragStopped = useCallback(params => {
    if (params.target.childElementCount > 1) {
        const colIds = params.columnApi.getAllDisplayedColumns().map(col => col.colId) // get new order 
        const value = columns.sort((a, b) => colIds.indexOf(a.colId) - colIds.indexOf(b.colId)) // apply the new order
        if (gridParams) {
        setColumns(value) // update the new order
    }
}
}, [ gridParams, setColumns ])

Upvotes: 0

ramaeon2
ramaeon2

Reputation: 41

 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>

Upvotes: 0

NearHuscarl
NearHuscarl

Reputation: 81520

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

Upvotes: 5

Roland
Roland

Reputation: 27759

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
}

Upvotes: 18

Related Questions