📝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 dynamically based on the columns in your row data. You will see how to bind and update column definitions in ag-Grid in each major framework. This lets you build a truly dynamic ag-grid that responds to the columns in your dataset rather than a static list of columns set beforehand.

You'll see how specific aspects of column state are preserved during these updates, allowing you to easily update columns without having to implement you own logic to reapply column state.

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

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!

Contents


Column State is maintained when updating columns

Whenever new column definitions are set in ag-Grid, specific aspects of state of the existing columns are automatically preserved. This allows you to easily update column definitions without having to write your own code to save and reapply 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.

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 simple! See the code below and note that the ag-grid-angular component has its columnDefs bound to a property in our component of the same name.

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

Any updates to the columnDefs property in  app.component will be reflected on our ag-Grid instance. 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 ag-Grid instance, simply by updating the columnDefs bound property, passing in a new set of column definitions.

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

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
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 ag-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 ag-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 React

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

When using React we have the option of declaring ag-Grid columns declaratively. In the example above you'll see that we're creating ag-Grid Columns by mapping over a state variable columns and returning a agGridColumn React component for each column definition, spreading props while doing so:

const App = () => {
 	const [columns, setColumns] = useState(colDefsAthleteExcluded);
  
	return (
		// ...
		{columns.map(column => (
			<AgGridColumn {...column} key={column.field} />
		))}

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 ag-Grid instance.
  • Columns that are not included in the new set will be removed from the ag-Grid instance.

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 ag-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 ag-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
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 ag-Grid instance. 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 ag-Grid instance, 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 ag-Grid instance.
  • Columns that are not included in the new set will be removed from the ag-Grid instance.

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 ag-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 ag-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 ag-Grid API method setColumnDefs() to set and update our columns.

Adding/removing columns from column definitions

To add or remove columns to our ag-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 ag-Grid instance.
  • Columns that are not included in the new set will be removed from the ag-Grid instance.

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 ag-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 ag-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
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);
}

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 in ag-Grid check out our documentation.

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

Happy coding!