如何在选择多个 mat-checkbox 时激活按钮并仅在未选择任何内容时停用按钮? (Angular material)

How to activate a button when selecting several mat-checkbox and deactivate it only when nothing is selected? (Angular material)

我正在使用 Angular Material 制作 table。在 table 中,我有数据,这些数据是从我在 JAVA 中创建的数据库中添加的。根据数据库中的行数(数据)创建复选框。这个想法是必须禁用将此数据发送到另一个 table 的按钮,并且它 必须仅启用 当至少有 1 个活动复选框时,如果没有活动复选框按钮必须被禁用。

问题是,当我取消选择 1 个复选框时,无论其他复选框是否处于活动状态,按钮都会被禁用。

HTML

<button mat-raised-button [disabled]="buttonDisable" (click)="procesarClic()">Enviar</button>

<ng-container matColumnDef="seleccionVarios">
              <mat-header-cell *matHeaderCellDef><label class="tituloTabla-verdoso text-center"> CHECKBOX </label></mat-header-cell>
              <mat-cell *matCellDef="let element">
                <mat-checkbox #checkbox (click)="$event.stopPropagation()"
                                        (change)="$event ? selection.toggle(element) : null; changeCheck($event)"
                                        [checked]="selection.isSelected(element)">
               </mat-checkbox>
             </mat-cell>
</ng-container>

TypeScript

export class PaginaPrincipal implements OnInit {
    buttonDisable: boolean = true;

changeCheck(event){
    this.buttonDisable = !event.checked;
  }

如果您想要 Angular 为您制作它,您只需要一个 FormArray 和一个自定义验证器。

如果你定义

checked:FormArray

当您创建数据源 (*) 时,例如在 ngOnInit

  ngOnInit() {
    this.dataSource = ELEMENT_DATA;

    this.checked = new FormArray(
      this.dataSource.map((x) => new FormControl()),
      this.someChecked()
    );
  }

你需要两个辅助功能:

  //A custom Validator
  someChecked() {
    return (form: AbstractControl) => {
      return form.value.find((x) => x)
        ? null
        : { error: 'almost one must be select' };
    };
  }

//and an auxiliar "getter"
checkedAt(index:number){
    return this.checked.at(index) as FormControl
}

您可以使用像

这样的单元格
<ng-container matColumnDef="seleccionVarios">
  <th mat-header-cell *matHeaderCellDef>...</th>
  <td mat-cell *matCellDef="let element;let i=index">
    <mat-checkbox [formControl]="checkedAt(i)"> </mat-checkbox>
  </td>
</ng-container>

还有你的按钮:

<button mat-button (click)="submit()" [disabled]="checked.errors">
submit
</button>

还有..瞧!此外,您可以获得像

这样的“选定”元素
submit()
{
    const selected=this.dataSource.filter((_,index)=>this.checked.value[index])
    console.log(selected)
}

看到一个simple stackblitz

(*)小心,在示例中数据源是一个数组,如果您使用 MatTableDataSource 则需要迭代 datasource.data

    this.dataSource=new MatTableDataSource<PeriodicElement>(ELEMENT_DATA);

    this.checked = new FormArray(
      this.dataSource.data.map((x) => new FormControl()),
      this.someChecked()
    );

//and in submit
const selected=this.dataSource.data.filter(
              (_,index)=>this.checked.value[index])

我发现此解决方案存在问题,当更改页面(使用分页器)以查看其他行时,复选框不会更改,它们仍然处于活动状态并且位于它们所在的相同位置被点击。如果它从另一页的其他行获取信息,但如果我有 16 行并且我想 select 所有这些,我将无法做到。分页器有 10 行,其他 6 行在分页器的另一页上,我不能 select 的是那些行,因为在更改分页器时它们已经 selected.

HTML:

<button mat-raised-button [disabled]="comprobarFilas()" (click)="procesarClic()">Solicitar</button>

<ng-container matColumnDef="seleccionVarios">
              <mat-header-cell *matHeaderCellDef><label class="tituloTabla-verdoso text-center"> CHECKBOX </label></mat-header-cell>
              <mat-cell *matCellDef="let element; let i=index">
                <mat-checkbox #checkbox ((click)="$event.stopPropagation()"
                                    (change)="$event ? selection.toggle(element) : null;"
                                    [checked]="selection.isSelected(element)"
                                    [formControl]="checkedAt(i)">
               </mat-checkbox>
             </mat-cell>
</ng-container>

TS:

     ngOnInit() {
        this.dataSource = ELEMENT_DATA;
    
        this.checked = new FormArray (
            this.dataSourceSolicitudNew.data.map((x) => new FormControl()),
            this.someChecked()
          );
      }
    
    someChecked() {
        return (form: AbstractControl) => {
          return form.value.find((x) => x)
            ? null
            : { error: 'almost one must be select' };
        };
      }
    
      checkedAt(index: number) {
        return this.checked.at(index) as FormControl;
      }
    
      comprobarFilas() {
        if(this.checked == null) {
            return false;
        }
        else {
          return this.checked.errors;
        }
    }

procesarClic() {
    const request = this.selection.selected
    const newTable = this.dialog.open(SolicitudNewDialog, {
      width: '400px',
      disableClose: true,
      data: { datosItem:request }
    });    
  }

“procesarClic()”函数打开一个对话框弹出窗口,我必须在其中显示我 selected 的项目列表。 感谢您的帮助!