I want to disable a button in a column using the click event of a button in another column in ag-grid.
I have used common service to disable it, but it disabled all the buttons in that column and I've also tried updating that column's field in params object(rowData), but didn't work.
Here is a sample on stackbltiz
Edit: Added source code
app.component.html
<h1>Hello World</h1>
<ag-grid-angular
style="width: 500px; height: 350px;"
class="ag-theme-alpine"
[rowData]="rowData"
[columnDefs]="columnDefs"
>
</ag-grid-angular>
app.component.ts
import { Component } from '@angular/core';
import { ColDef } from 'ag-grid-community';
import { ButtonRendererComponent } from './button-renderer/button-renderer.component';
@Component({
selector: 'my-app',
styleUrls: ['./app.component.css'],
templateUrl: './app.component.html',
})
export class AppComponent {
columnDefs: ColDef[] = [
{
field: 'make',
headerName: 'Button1',
cellRenderer: ButtonRendererComponent,
cellRendererParams: {
comp: 'label1',
},
},
{
field: 'model',
headerName: 'Button1',
cellRenderer: ButtonRendererComponent,
cellRendererParams: {
comp: 'label2',
},
},
{ field: 'price' },
];
rowData = [
{
make: 'Toyota',
model: 'Celica',
price: 35000,
button1: true,
button2: false,
},
{
make: 'Ford',
model: 'Mondeo',
price: 32000,
button1: true, //fetched from DB
button2: false, //fetched from DB
},
{
make: 'Porsche',
model: 'Boxster',
price: 72000,
button1: true, //fetched from DB
button2: false, //fetched from DB
},
];
}
button-renderer.component.html
<button
*ngIf="params['comp'] == 'label1'"
mat-flat-button
color="primary"
(click)="clickButton1()"
[disabled]="isButton1Disabled"
>
Button1
</button>
<button
*ngIf="params['comp'] == 'label2'"
mat-flat-button
color="primary"
(click)="clickButton2()"
[disabled]="comSvc.isButtonDisabled"
>
Button2
</button>
button-renderer.component.ts
import { Component, OnInit } from '@angular/core';
import { ICellRendererAngularComp } from 'ag-grid-angular';
import { ICellRendererParams } from 'ag-grid-community';
import { CommonService } from '../common.service';
@Component({
selector: 'app-button-renderer',
templateUrl: './button-renderer.component.html',
styleUrls: ['./button-renderer.component.css'],
})
export class ButtonRendererComponent implements ICellRendererAngularComp {
params: any;
isButton1Disabled: boolean = false;
isButton2Disabled: boolean = true;
agInit(params: ICellRendererParams): void {
this.params = params;
}
// gets called whenever the cell refreshes
refresh(params: ICellRendererParams): boolean {
// set value into cell again
return true;
}
constructor(public comSvc: CommonService) {}
ngOnInit() {}
clickButton1() {
console.log('Button 1 is clicked');
// this.isButton2Disabled = true;
// this.params.button2 = true;
this.comSvc.isButtonDisabled = true;
//DB update call
}
clickButton2() {
console.log('Button 2 is clicked');
//DB update call
}
}
Packages:
Angular: 16.2.0
ag-grid-angular: 30.2.0
This is normal to disable every buttons with you current code, as the service is common for every components and you have only one state for the button. This means all buttons have the same disabled state.
cell renderer component html:
<button *ngIf="params['comp'] == 'label1'" mat-flat-button color="primary" (click)="clickButton1()">
Button1
</button>
<button *ngIf="params['comp'] == 'label2'" mat-flat-button color="primary" (click)="clickButton2()" [disabled]="comSvc.isDisabled(this.params.rowIndex)">
Button2
</button>
cell renderer component ts:
import { Component, OnInit } from '@angular/core';
import { ICellRendererAngularComp } from 'ag-grid-angular';
import { ICellRendererParams } from 'ag-grid-community';
import { CommonService } from '../common.service';
@Component({
selector: 'app-button-renderer',
templateUrl: './button-renderer.component.html',
})
export class ButtonRendererComponent implements ICellRendererAngularComp {
params: any;
agInit(params: ICellRendererParams): void {
this.params = params;
}
// gets called whenever the cell refreshes
refresh(params: ICellRendererParams): boolean {
// set value into cell again
return true;
}
constructor(public comSvc: CommonService) {}
clickButton1() {
console.log(`Button 1 is clicked on row index${this.params.rowIndex}`);
this.comSvc.disableButtonOnRow(this.params.rowIndex);
//DB update call
}
clickButton2() {
console.log('Button 2 is clicked');
//DB update call
}
}
the service:
import { Injectable } from '@angular/core';
@Injectable()
export class CommonService {
private disabledButtonByRow = new Map<number, boolean>();
public disableButtonOnRow(rowId: number): void {
this.disabledButtonByRow.set(rowId, true);
}
public isDisabled(rowId: number): boolean {
console.log('is disabled is called!' + rowId);
return !!(
this.disabledButtonByRow.has(rowId) && this.disabledButtonByRow.get(rowId)
);
}
}
cell renderer component html:
<button mat-flat-button color="primary" (click)="clickButton1()">
Button1
</button>
<button mat-flat-button color="primary" (click)="clickButton2()" [disabled]="button2DisabledState">
Button2
</button>
cell renderer component ts:
import { Component } from '@angular/core';
import { ICellRendererAngularComp } from 'ag-grid-angular';
import { ICellRendererParams } from 'ag-grid-community';
@Component({
selector: 'app-button-renderer',
templateUrl: './button-renderer.component.html',
})
export class ButtonRendererComponent implements ICellRendererAngularComp {
button2DisabledState= false;
agInit(): void {
}
// gets called whenever the cell refreshes
refresh(params: ICellRendererParams): boolean {
// set value into cell again
return false;
}
clickButton1() {
this.button2DisabledState= true;
//DB update call
}
clickButton2() {
console.log('Button 2 is clicked');
//DB update call
}
}
table component ts:
import { Component } from '@angular/core';
import { ColDef } from 'ag-grid-community';
import { ButtonRendererComponent } from './button-renderer/button-renderer.component';
@Component({
selector: 'my-app',
styleUrls: ['./app.component.css'],
templateUrl: './app.component.html',
})
export class AppComponent {
columnDefs: ColDef[] = [
{
field: 'make',
headerName: 'Button1 & 2',
cellRenderer: ButtonRendererComponent,
flex:2
},
{ field: 'price',
flex: 1
},
];
rowData = [
{
make: 'Toyota',
model: 'Celica',
price: 35000,
button1: true,
button2: false,
},
{
make: 'Ford',
model: 'Mondeo',
price: 32000,
button1: true, //fetched from DB
button2: false, //fetched from DB
},
{
make: 'Porsche',
model: 'Boxster',
price: 72000,
button1: true, //fetched from DB
button2: false, //fetched from DB
},
];
}
cell renderer component html:
<button
mat-flat-button
color="primary"
(click)="params.actionOnClick()"
[disabled]="params.value"
>
{{params.buttonName}}
</button>
cell renderer component ts:
import { Component, OnInit } from '@angular/core';
import { ICellRendererAngularComp } from 'ag-grid-angular';
import { ICellRendererParams } from 'ag-grid-community';
@Component({
selector: 'app-button-renderer',
templateUrl: './button-renderer.component.html',
})
export class ButtonRendererComponent implements ICellRendererAngularComp {
params: any;
agInit(params: ICellRendererParams): void {
this.params = params;
}
// gets called whenever the cell refreshes
refresh(params: ICellRendererParams): boolean {
// set value into cell again
return false;
}
}
table component ts:
import { Component } from '@angular/core';
import { ColDef } from 'ag-grid-community';
import { ButtonRendererComponent } from './button-renderer/button-renderer.component';
@Component({
selector: 'my-app',
styleUrls: ['./app.component.css'],
templateUrl: './app.component.html',
})
export class AppComponent {
columnDefs: ColDef[] = [
{
field: 'button1',
headerName: 'Button1',
cellRenderer: ButtonRendererComponent,
cellRendererParams: (params: any) => ({
buttonName: 'Button 1',
actionOnClick: () => {
console.log(`Button 1 is clicked on row index${params.rowIndex}`);
this.rowData[params.rowIndex].button2 = true;
// force aggrid to detect changes in row Data
this.rowData = [...this.rowData];
},
}),
},
{
field: 'button2',
headerName: 'Button2',
cellRenderer: ButtonRendererComponent,
cellRendererParams: {
buttonName: 'Button 2',
actionOnClick: () => {
console.log('Button 2 is clicked');
//DB update call
},
},
},
{ field: 'price' },
];
rowData = [
{
make: 'Toyota',
model: 'Celica',
price: 35000,
button1: false,
button2: false,
},
{
make: 'Ford',
model: 'Mondeo',
price: 32000,
button1: false, //fetched from DB
button2: false, //fetched from DB
},
{
make: 'Porsche',
model: 'Boxster',
price: 72000,
button1: true, //fetched from DB
button2: false, //fetched from DB
},
];
}
The important part here, is this.rowData = [...this.rowData];
, which helps aggrid to detect changes in the rowData