Home > other >  How to activate a button when selecting several mat-checkbox and deactivate it only when nothing is
How to activate a button when selecting several mat-checkbox and deactivate it only when nothing is

Time:11-05

I'm making a table using Angular Material. Inside the table I have data, which is added from a DB that I have created in JAVA. The checkboxes are created depending on the number of rows (data) that are in the DB. The idea is that the button to send this data to another table MUST BE disabled and it MUST ONLY BE ENABLED when there is at least 1 active checkbox, if there is no active checkbox the button must be disabled.

The problem is that when I deselect 1 checkbox the button is disabled, regardless of whether the other checkboxes are active.

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;
  }

CodePudding user response:

if you want that Angular make it for you, you only need a FormArray and a custom validator.

If your define

checked:FormArray

When you create the dataSource (*), e.g. in ngOnInit

  ngOnInit() {
    this.dataSource = ELEMENT_DATA;

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

You need two auxiliars function:

  //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
}

You can use a cell like

<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>

And your button:

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

And.. voilá! Futhermore you can get the "selected" elements like

submit()
{
    const selected=this.dataSource.filter((_,index)=>this.checked.value[index])
    console.log(selected)
}

see a simple stackblitz

(*)Be carefull, in the example the dataSource is an array, if you use a MatTableDataSource you need iterate over 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])
  • Related