首页 > 解决方案 > Enable/Disable input field in mat-table when checkbox is selected (Angular 8)

问题描述

I have multiple input fields on a mat table, and I want them to be enabled only when the row's checkbox is selected, or disabled when the row's checkbox is deselected. Currently, when I select one checkbox, it enables all the input fields. When I deselect the checkbox it disables all the input fields. Any help on this is appreciated. Thanks.

Selected checkbox enables all text fields

HTML

                            <form [formGroup]="batchRentalExtensionForm">
<div class="screen-container">
    <div class="card-wrapper">
        <div class="heading-content">{{constant.BATCHRENTALEXTENSION}}</div>
        <mat-divider class="mat-divider-content"></mat-divider>
        <div class="card-content" style="width:55%">
            <div>
                <div fxLayout="row" fxLayoutAlign="space-between none" fxFlex="50">
                    <mat-form-field>
                        <mat-label>{{constant.LOCATION}}</mat-label>
                        <mat-select disableRipple>
                            <mat-option value="1">Home Office</mat-option>
                            <mat-option value="2">Call Center</mat-option>
                        </mat-select>
                    </mat-form-field>
                </div>
                <div fxLayout="row" fxLayoutAlign="space-between none" fxFlex="50">
                    <mat-form-field>
                        <mat-select disableRipple>
                            <mat-option value="1">All</mat-option>
                        </mat-select>
                    </mat-form-field>
                </div>
            </div>
            <div class="mat-elevation-z8 batchRentalExtensionFormTable">
                <div>
                    <table mat-table [dataSource]="dataSource" matSort>
                        <ng-container matColumnDef="select">
                            <th mat-header-cell *matHeaderCellDef>
                                <mat-checkbox (change)="$event ? masterToggle() : null"
                                    [checked]="selection.hasValue() && isAllSelected()"
                                    [indeterminate]="selection.hasValue() && !isAllSelected()">
                                </mat-checkbox>
                            </th>
                            <td mat-cell *matCellDef="let row">
                                <mat-checkbox (click)="$event.stopPropagation()"
                                    (change)="$event ? selection.toggle(row) : null"
                                    [checked]="selection.isSelected(row)">
                                </mat-checkbox>
                            </td>
                        </ng-container>
                        <ng-container matColumnDef="position">
                            <th mat-header-cell *matHeaderCellDef mat-sort-header> Client No. </th>
                            <td mat-cell *matCellDef="let element"> {{element.position}} </td>
                        </ng-container>
                        <ng-container matColumnDef="claimNo">
                            <th mat-header-cell *matHeaderCellDef mat-sort-header> Claim No.</th>
                            <td mat-cell *matCellDef="let element"> {{element.claimNo}} </td>
                        </ng-container>
                        <ng-container matColumnDef="rentersName">
                            <th mat-header-cell *matHeaderCellDef mat-sort-header> Renter's Name </th>
                            <td mat-cell *matCellDef="let element"> {{element.rentersName}} </td>
                        </ng-container>
                        <ng-container matColumnDef="lor">
                            <th mat-header-cell *matHeaderCellDef mat-sort-header> LOR </th>
                            <td mat-cell *matCellDef="let element"> {{element.lor}} </td>
                        </ng-container>
                        <ng-container matColumnDef="state">
                            <th mat-header-cell *matHeaderCellDef mat-sort-header> State </th>
                            <td mat-cell *matCellDef="let element"> {{element.state}} </td>
                        </ng-container>
                        <ng-container matColumnDef="authDate">
                            <th mat-header-cell *matHeaderCellDef mat-sort-header> Auth Date </th>
                            <td mat-cell *matCellDef="let element"> {{element.authDate}} </td>
                        </ng-container>
                        <ng-container matColumnDef="addDays">
                            <th mat-header-cell *matHeaderCellDef> Add Days </th>
                            <td mat-cell *matCellDef="let element"> <input type="number"
                                    [disabled]="isAddDaysEnabled" placeholder="0"> </td>
                        </ng-container>
                        <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
                        <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
                    </table>
                </div>

                <mat-paginator [pageSizeOptions]="[5, 10, 20]" showFirstLastButtons></mat-paginator>
            </div>
            <div fxLayout="row" style="margin-top:60px">
                <button type="button" class="button btn-secondary btn-sm">{{constant.EXTENDRENTAL}}</button>
            </div>
        </div>
    </div>
</div>

TS

export class BatchRentalExtensionHomeComponent implements OnInit {
    
      batchRentalExtensionForm: FormGroup;
      @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator;
      batchRentalExtensionTable: batchRentalExtensionObj[] = [
        { position: '1', claimNo: '4234234', rentersName: 'fsgdfg', lor: '21', state: 'CA', authDate: '01/19/2021', addDays: '0' },
        { position: '2', claimNo: '3242344', rentersName: 'uiyui', lor: '21', state: 'CA', authDate: '01/19/2021', addDays: '0' }, 
        { position: '3', claimNo: '67567567', rentersName: 'tyrtryt', lor: '21', state: 'CA', authDate: '01/19/2021', addDays: '0' },
        { position: '4', claimNo: '234234', rentersName: 'fhfghfgh', lor: '21', state: 'CA', authDate: '01/19/2021', addDays: '0' },
        { position: '5', claimNo: '5675676', rentersName: 'erwerwer', lor: '21', state: 'CA', authDate: '01/19/2021', addDays: '0' },
    
    
    
      ];
      selection = new SelectionModel<batchRentalExtensionObj>(true, []);
      dataSource = new MatTableDataSource<batchRentalExtensionObj>(this.batchRentalExtensionTable);
      displayedColumns: string[] = ['select', 'position', 'claimNo', 'rentersName', 'lor', 'state', 'authDate', 'addDays'];
      isAddDaysEnabled: boolean = true;
    
      @ViewChild(MatSort, { static: false }) sort: MatSort;
    
      constructor(public commonService: CommonService, private fb: FormBuilder, public constant: Constants,) {
        this.selection.changed.subscribe(item => {
          this.isAddDaysEnabled = this.selection.selected.length == 0;
          })
       }
    
    
      ngOnInit() {
        this.initBatchRentalExtensionForm();
      }
    
      ngAfterViewInit() {
        this.dataSource.paginator = this.paginator;
        this.dataSource.sort = this.sort;
    
      }
    
      initBatchRentalExtensionForm() {
        this.batchRentalExtensionForm = this.fb.group({})
      }
      masterToggle() {
    
        if (this.isAllSelected()) {
          this.selection.clear()
          this.isAddDaysEnabled = true;
        } else {
          this.dataSource.data.forEach(row => this.selection.select(row));
          this.isAddDaysEnabled = false;
        }
    
      }
      isAllSelected() {
        const numSelected = this.selection.selected.length;
        const numRows = this.dataSource.data.length;
        return numSelected === numRows;
      }
    
    }

标签: angularangular-material

解决方案


首先,您需要定义一个索引,以便您知道每一行的索引:

<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>

需要是: <tr mat-row *matRowDef="let row; columns: displayedColumns; let i = index"></tr>

[disabled]="isAddDaysEnabled"正在使用一个奇异变量,因此每次触发复选框时都会更新这个变量。每行都使用相同的变量,这就是为什么每行上的输入都被禁用或启用的原因。你想使用基于行索引的数组,所以像这样:

<input type="number" [disabled]="isAddDaysEnabled[i]" placeholder="0">

所以现在我们有一个数组,可以根据行索引定位数组中的特定位置,以确定是否应该启用或禁用此行输入。

然后,您需要将该 TS 中的变量转换为数组。当您切换复选框时,您在 TS 中调用的方法需要根据单击的行索引设置值。看起来您正在为此使用它: this.selection.changed.subscribe(item => { this.isAddDaysEnabled = this.selection.selected.length == 0; })

如果item有行索引,你可以使用它。否则,您必须将 HTML 中的行索引传递到方法/订阅中。所以你想基本上做这样的事情:

this.isAddDaysEnabled[i] = this.selection.selected.length == 0;

希望这会为您指明正确的方向!


推荐阅读