Angular 无法在ag-grid中禁用按钮

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的变化

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程