Angular 无法在ag-grid中禁用按钮
问题描述
我想通过在ag-grid中的另一列的按钮的点击事件来禁用列中的某个按钮。
我已经尝试使用常见的服务来禁用它,但是它禁用了该列中的所有按钮,我还尝试在params对象(rowData)中更新该列的字段,但没有起效果。
这里是一个在stackbltiz上的示例:
源代码:
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
},
];
}
按钮渲染器组件.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
}
}
包裹:
Angular: 16.2.0
ag-grid-angular: 30.2.0
解决方案
通过您当前的代码禁用每个按钮是正常的,因为该服务适用于所有组件,并且按钮只有一种状态。这意味着所有按钮都具有相同的禁用状态。
解决方案1:使用一个服务来保持所有行的禁用状态
单元格渲染器组件的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组件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
}
}
服务:
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)
);
}
}
解决方案2:将两个按钮放在同一个单元格渲染器中
单元格渲染器组件的HTML代码:
<button mat-flat-button color="primary" (click)="clickButton1()">
Button1
</button>
<button mat-flat-button color="primary" (click)="clickButton2()" [disabled]="button2DisabledState">
Button2
</button>
单元格渲染器组件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
}
}
表格组件 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
},
];
}
解决方案3:更新行数据以刷新单元格渲染器
单元格渲染器组件的HTML:
<button
mat-flat-button
color="primary"
(click)="params.actionOnClick()"
[disabled]="params.value"
>
{{params.buttonName}}
</button>
单元格渲染器组件 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;
}
}
表格组件 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
},
];
}
这里的重要部分是 this.rowData = [...this.rowData];
,这可以帮助aggrid检测rowData的变化