
ag-Grid gives great flexibility in the ways you can render content in cells. A common scenario is to display a button in a column of cells to do some additional processing.
In this post, we'll show you how to render buttons within a column - you can see the final result in the screenshot below.

Vanilla JavaScript
We're using the ES5 Class syntax to construct our renderer here, placing the required init
and getGui
hooks on the prototype object. We create a DOM element in the init
method, which is then returned in the getGui
method. The optional destroy
hook has also included to do some cleanup (removing the click listener from our component).
// btn-cell-renderer.js
function BtnCellRenderer() {}
BtnCellRenderer.prototype.init = function(params) {
this.params = params;
this.eGui = document.createElement('button');
this.eGui.innerHTML = 'Click me!';
this.btnClickedHandler = this.btnClickedHandler.bind(this);
this.eGui.addEventListener('click', this.btnClickedHandler);
}
BtnCellRenderer.prototype.getGui = function() {
return this.eGui;
}
BtnCellRenderer.prototype.destroy = function() {
this.eGui.removeEventListener('click', this.btnClickedHandler);
}
BtnCellRenderer.prototype.btnClickedHandler = function(event) {
this.params.clicked(this.params.value);
}
The renderer is registered to ag-Grid in gridOptions.components
and is used on the athlete column. Note that we're passing the button click handler dynamically to our renderer via cellRendererParams
- this makes for a more flexible and reusable renderer.
// main.js
var gridOptions = {
columnDefs: [
{
field: 'athlete',
cellRenderer: 'btnCellRenderer',
cellRendererParams: {
clicked: function(field) {
alert(`${field} was clicked`);
}
},
minWidth: 150
},
// [...]
components: {
btnCellRenderer: BtnCellRenderer
}
};
Learn more about JavaScript Cell Renderers.
Angular
Here we create the button cell renderer as an Angular component that implements the ICellRendererAngularComp
interface. Access to the params object can be found on the agInit
hook.
// app/button-cell-renderer.component.ts
@Component({
selector: 'btn-cell-renderer',
template: `
<button (click)="btnClickedHandler($event)">Click me!</button>
`,
})
export class BtnCellRenderer implements ICellRendererAngularComp, OnDestroy {
private params: any;
agInit(params: any): void {
this.params = params;
}
btnClickedHandler() {
this.params.clicked(this.params.value);
}
ngOnDestroy() {
// no need to remove the button click handler
// https://stackoverflow.com/questions/49083993/does-angular-automatically-remove-template-event-listeners
}
}
The renderer is registered to ag-Grid via gridOptions.frameworkComponents
. Note that we're passing the button click handler dynamically to our renderer via cellRendererParams
- allowing for a more flexible and reusable renderer.
// app/app.component.ts
this.columnDefs = [
{
field: 'athlete',
cellRenderer: 'btnCellRenderer',
cellRendererParams: {
clicked: function(field: any) {
alert(`${field} was clicked`);
}
},
minWidth: 150,
}
// [...]
];
this.frameworkComponents = {
btnCellRenderer: BtnCellRenderer
};
It is also necessary to pass our renderer to our @NgModule
decorator to allow for dependency injection.
// app/app.modules.ts
@NgModule({
imports: [
BrowserModule,
FormsModule,
HttpClientModule,
AgGridModule.withComponents([BtnCellRenderer]),
],
declarations: [AppComponent, BtnCellRenderer],
bootstrap: [AppComponent],
})
Learn more about Angular Cell Renderers
React
Here our button cell renderer is constructed as a (you guessed it!) React component. The only thing to take note of here is that cell params will be available on the component via props
.
// BtnCellRenderer.jsx
class BtnCellRenderer extends Component {
constructor(props) {
super(props);
this.btnClickedHandler = this.btnClickedHandler.bind(this);
}
btnClickedHandler() {
this.props.clicked(this.props.value);
}
render() {
return (
<button onClick={this.btnClickedHandler}>Click Me!</button>
)
}
}
Just as with Angular, the renderer is registered to ag-Grid via gridOptions.frameworkComponents
. The button click handler is passed to our renderer at run time via cellRendererParams
- allowing for a more flexible and reusable renderer.
// index.jsx
columnDefs: [
{
field: 'athlete',
cellRenderer: 'btnCellRenderer',
cellRendererParams: {
clicked: function(field) {
alert(`${field} was clicked`);
},
},
// [...]
}
frameworkComponents: {
btnCellRenderer: BtnCellRenderer,
}
Learn more about React Cell Renderers
Vue.js
Configuring the renderer in Vue.js is extremely simple:
// btn-cell-renderer.js
export default Vue.extend({
template: `
<span>
<button @click="btnClickedHandler()">Click me!</button>
</span>
`,
methods: {
btnClickedHandler() {
this.params.clicked(this.params.value);
}
},
});
As with the other frameworks, the renderer is registered to ag-Grid via gridOptions.frameworkComponents
and the button click handler is passed to our renderer at run time via cellRendererParams
- allowing for a more flexible and reusable renderer.
// main.js
this.columnDefs = [
{
field: 'athlete',
cellRenderer: 'btnCellRenderer',
cellRendererParams: {
clicked: function(field) {
alert(`${field} was clicked`);
}
},
// [...]
],
this.frameworkComponents = {
btnCellRenderer: BtnCellRenderer
}
Learn more about Vue.js Cell Renderers
What's next?
I hope you find this article useful when configuring buttons in the cells of ag-Grid. Please check out our other blog posts and documentation for a great variety of scenarios you can implement with ag-Grid.
If you would like to try out ag-Grid check out our getting started guides (JS / React / Angular / Vue)
Happy coding!