Using Dynamic Column Definitions in AG Grid

  |   How To
📝This blog post was inspired by a popular Stack Overflow question.

In this post we'll go over how to set AG Grid column definitions and also how to update them in place for each major framework. You'll see how specific aspects of column state are preserved during these updates, allowing you to update columns without having to implement you own logic to re-apply column state.

We demonstrate this with live examples in Angular, React, Vue.JS and JavaScript.

Contents


Column State is maintained when updating columns

Whenever new column definitions are set in AG Grid, specific aspects of the state of the existing columns are automatically preserved. This allows you to update column definitions without having to write your own code to save and re-apply column state.

Column state is kept for sorting, filtering, column width, pinned columns, column order etc. See the full list of stateful attributes of column definitions and how to save and apply column state in our documentation.

The GIF below shows how adding, removing and even updating columns does not reset column state - we sort the AGE column, resize the COUNTRY column, filter the SPORT column, and all this state is preserved when we add a new ATHLETE column or set header names by clicking the buttons above the grid.

Maintain Column Order

When Column Definitions are provided to the grid, the order of the Columns inside the grid is set to match the order of the newly provided Column Definitions. This means every time Columns are set, the order is guaranteed to match the order of the definitions. This is usually the desired and expected behaviour.

You may wish for the order of the Columns to not match the Column Definitions. For example suppose the user has rearranged Columns to their desired order, and then the application updates the Column Definitions (e.g. changes the Cell Renderer used), then it would be undesirable to reset the Column order, as the users arranged order would be lost.

If the desired behaviour is that Column's order should be maintained, set the grid property maintainColumnOrder=true. You can read more about this and see an example in the documentation.

Binding and Updating Column Definitions in Angular

Let's look into how to implement this when using Angular. Please see the live sample below:

Binding column definitions

Binding and updating column definitions in Angular is handled by the ag-grid-angular component Input columnDefs.

<ag-grid-angular
    style="width: 100%; height: 300px;"
    class="ag-theme-alpine"
    [columnDefs]="columnDefs"

Any updates to the columnDefs property in your component will be reflected in the grid. For example, see how we set the initial column definitions in the app.component's constructor function:

constructor(private http: HttpClient) {
	//...
    this.columnDefs = colDefsAthleteExcluded;
}

Adding/removing columns from column definitions

We can add or remove columns in our grid by updating the columnDefs property, passing in a new set of column definitions.

  • Columns that didn't exist previously will be added to the grid.
  • Columns that are not included in the new set will be removed from the grid.

The code below has two event handlers for updating the columns to a different set of column definitions.

// removes the athlete column
onBtExcludeAthleteColumn() {
	this.columnDefs = colDefsAthleteExcluded;
}
  
// adds the athlete column
onBtIncludeAthleteColumn() {
	this.columnDefs = colDefsAthleteIncluded;
}

Updating existing column definitions

To update existing column definitions, we first call the grid API method getColumnDefs() to get a reference to the grid's current columns. We then map over the columns, changing any desired properties before updating our columnDefs bound property.

AG Grid will match existing columns with those in our grid and update the columns that have changed. You can get more details on updating column definitions in our documentation.

The code below updates the header name for every column:

// sets each columns headerName property
setHeaderNames() {
	var columnDefs = this.gridApi.getColumnDefs();
	columnDefs.forEach(function(colDef, index) {
  		colDef.headerName = "C" + index;
	});
	this.columnDefs = columnDefs;
}
  
  
// clears each columns headerName property
removeHeaderNames() {
	var columnDefs = this.gridApi.getColumnDefs();
    columnDefs.forEach(function(colDef, index) {
    	colDef.headerName = undefined;
    });
    this.columnDefs = columnDefs;
}

Binding and Updating Column Definitions in React

Let's look into how to implement this when using React. Please see the live sample below:

When using React we can bind our column definitions to the columnDefs prop on the AgGridReact component:

const App = () => {
 	const [columns, setColumns] = useState(colDefsAthleteExcluded);
  
	return (
		<AgGridReact
              rowData={rowData}
              columnDefs={columns}

Any updates to the columnDefs prop in your component will be reflected in the grid.

Adding/removing columns from column definitions

To add or remove columns, we simply have to call the setColumns setState method, passing in a new set of column definitions.

  • Columns that didn't exist previously will be added to the grid.
  • Columns that are not included in the new set will be removed from the grid.

Please see the code for this below in the event handlers for the "Include Athlete Column" and "Exclude Athlete Column" buttons:

// removes the athlete column
const onBtExcludeAthleteColumn = () => {
    setColumns(colDefsAthleteExcluded);
  };

// adds the athlete column
  const onBtIncludeAthleteColumn = () => {
    setColumns(colDefsAthleteIncluded);
  };

Updating existing column definitions

To update existing column definitions, we first call the grid API method getColumnDefs() to get a reference to the grid's current columns. We then map over the columns, changing any desired properties before calling setColumns and updating our columns state variable.

AG Grid will then match existing columns with those in our grid and update the columns that have changed. You can get more details on updating column definitions in our documentation.

Please see the code for this below in the event handlers for the "Set HeaderNames" and "Remove HeaderNames" buttons:

// sets each columns headerName property
const setHeaderNames = () => {
    const newColumns = gridApi.getColumnDefs();
    newColumns.forEach((newColumn, index) => {
      newColumn.headerName = "C" + index;
    });
    setColumns(newColumns);
  };

// clears each columns headerName property
  const removeHeaderNames = () => {
    const newColumns = gridApi.getColumnDefs();
    newColumns.forEach((newColumn, index) => {
      newColumn.headerName = undefined;
    });
    setColumns(newColumns);
  };

Binding and Updating Column Definitions in Vue.js

You can easily implement binding and updating column definitions in Vue.js. Please see the live example below:

Below you'll see that our ag-grid-vue component has its columnDefs bound to a property in our component of the same name.

 <ag-grid-vue
    style="width: 100%; height: 300px;"
    class="ag-theme-alpine"
    id="myGrid"
    :columnDefs="columnDefs"

Any updates to the columnDefs property in Vue component will be reflected in our grid. For example, see how we set the initial column definitions in the beforeMount lifecycle method:

beforeMount() {
	// ...
	this.columnDefs = colDefsAthleteExcluded;
}

Adding/removing columns from column definitions

To add or remove columns to our grid, we update the columnDefs bound property, passing in a new set of column definitions.

  • Columns that didn't exist previously will be added to the grid.
  • Columns that are not included in the new set will be removed from the grid.

Please see the code for this below in the event handlers for the "Include Athlete Column" and "Exclude Athlete Column" buttons:

 // removes the athlete column
btnExcludeAthleteColumn() {
	this.columnDefs = colDefsAthleteExcluded;
},  
// adds the athlete column
btnIncludeAthleteColumn() {
	this.columnDefs = colDefsAthleteIncluded;
}

Updating existing column definitions

To update existing column definitions, we first call the grid API method getColumnDefs() to get a reference to the grid's current columns. We then map over the columns, changing any desired properties before updating our columnDefs bound property.

AG Grid will then match existing columns with those in our grid instance and update the columns that have changed. You can get more details on updating column definitions in our documentation.

Please see the code for this below in the event handlers for the "Set HeaderNames" and "Remove HeaderNames" buttons:

// sets each columns headerName property
setHeaderNames() {
    var columnDefs = this.gridApi.getColumnDefs();
    columnDefs.forEach(function(colDef, index) {
		colDef.headerName = "C" + index;
    });
    this.columnDefs = columnDefs;
}
  
  
// clears each columns headerName property
removeHeaderNames() {
    var columnDefs = this.gridApi.getColumnDefs();
    columnDefs.forEach(function(colDef, index) {
		colDef.headerName = undefined;
    });
    this.columnDefs = columnDefs;
}

Binding and Updating Column Definitions in Vanilla JavaScript

You can easily implement binding and updating column definitions in JavaScript. Please see the live example below:

When using vanilla JS, column definitions cannot be bound to a property within our application as JavaScript does not have a built-in mechanism for reactive data. Instead we use the grid API method setColumnDefs() to set and update our columns.

Adding/removing columns from column definitions

To add or remove columns to our grid instance, we call the setColumnDefs API, passing in a new set of column definitions.

  • Columns that didn't exist previously will be added to the grid.
  • Columns that are not included in the new set will be removed from the grid.

Please see the code for this below in the event handlers for the "Include Athlete Column" and "Exclude Athlete Column" buttons:

// removes athlete column
function onBtExcludeAthleteColumn() {
	gridOptions.api.setColumnDefs(colDefsAthleteExcluded);
}

// adds athlete column
function onBtIncludeAthleteColumn() {
	gridOptions.api.setColumnDefs(colDefsAthleteIncluded);
}

Updating existing column definitions

To update existing column definitions, we first call the grid API method getColumnDefs() to get a reference to the grid's current columns. We then map over the columns, changing any desired properties before calling setColumnDefs(colDefs) and passing in the updated columns.

AG Grid will then match existing columns with those in our instance and update the columns that have changed. You can get more details on updating column definitions in our documentation.

Please see the code for this below in the event handlers for the "Set HeaderNames" and "Remove HeaderNames" buttons:

// sets each columns headerName property
function setHeaderNames() {
    var columnDefs = gridOptions.api.getColumnDefs();
    columnDefs.forEach(function(colDef, index) {
    	colDef.headerName = "C" + index;
    });
    gridOptions.api.setColumnDefs(columnDefs);
}

// clears each columns headerName property
function removeHeaderNames() {
    var columnDefs = gridOptions.api.getColumnDefs();
    columnDefs.forEach(function(colDef, index) {
    	colDef.headerName = undefined;
    });
    gridOptions.api.setColumnDefs(columnDefs);
}

Note: As of AG Grid version 24, there is no longer a need to set immutableColumns in your gridOptions (previously known as deltaColumnMode) as columns are reactive by default!

What's next?

We hope that you find this article useful whenever you're looking to bind and update column definitions in AG Grid. To learn more about updating columns check out our documentation.

You might also find the following blog posts useful:

If you would like to try out AG Grid check out our getting started guides (JS / React / Angular / Vue)

Happy coding!

Read more posts about...