Reputation: 999
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
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
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
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
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.
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 };
}
// in render()
const { onDragStarted, onDragStopped } = useDragColumnChange(e => console.log('Saving new column order!'))
return (
<AgGridReact
...
onDragStarted={onDragStarted}
onDragStopped={onDragStopped}
/>
);
Upvotes: 5
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