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