4

I have the following markup:

<table>
  <thead>
    <th *ngFor="let column of columnNames">
      <ng-container *ngIf="column === 'Column6'; else normalColumns">
        {{column}} <input type="checkbox" #chkAll />
      </ng-container>
      <ng-template #normalColumns>
        {{column}}
      </ng-template>
    </th>
  </thead>
  <tbody>
    <tr>
      <td *ngFor="let model of columnValues">
        <ng-container *ngIf="model === 'Value6'; else normal">
        {{model}} <input type="checkbox" [checked]="chkAll?.checked" />
      </ng-container>
      <ng-template #normal>
        {{model}}
      </ng-template>
      </td>
    </tr>
  </tbody>
</table>

I would like to implement a "Select All" feature.

As you can see, I have the condition in the table header, that if the header name is equal to a certain value, add an input on that header. In the table body, I also have a condition, on whether there should be added an checkbox to the column or not.

When I select the #chkAll checkbox in the table header, I would like the checkboxes in the rows below, to also be selected. I thought that [checked]="chkAll?.checked" on the checkboxes would do the trick, but it does not work.

Here is my Stackblitz

2 Answers 2

4

Since the chkAll variable is defined in a separate template (created by the ngFor loop of the header), it is not available in the markup of the table body.

You can call a component method when the header checkbox value changes, to perform the check/uncheck of the checkboxes in the rows:

<table>
  <thead>
    <th *ngFor="let column of columnNames">
      <ng-container *ngIf="column === 'Column6'; else normalColumns">
        {{column}} <input type="checkbox" ngModel (ngModelChange)="checkAllBoxes($event)" />
      </ng-container>
      ...
    </th>
  </thead>
  <tbody>
    <tr>
      <td *ngFor="let model of columnValues">
        <ng-container *ngIf="model === 'Value6'; else normal">
          {{model}} <input type="checkbox" #chkBox />
        </ng-container>
        ...
      </td>
    </tr>
  </tbody>
</table>

The checkAllBoxes method uses the QueryList provided by ViewChildren to access the checkboxes:

@ViewChildren("chkBox") private chkBoxes: QueryList<ElementRef>;

checkAllBoxes(value: boolean) {
  this.chkBoxes.forEach(chk => {
    chk.nativeElement.checked = value;
  });
}

See this stackblitz for a demo.

Sign up to request clarification or add additional context in comments.

1 Comment

I did not realize that the template reference variable will not work across different templates. Thanks for your solution, will keep this in mind.
2

Another way to do this is as follows:

In your template:

<table>
  <thead>
    <th *ngFor="let column of columnNames">
      <ng-container *ngIf="column === 'Column6'; else normalColumns">
        {{column}} <input type="checkbox" #chkAll ngModel (change)="checkAll = chkAll.checked" />
      </ng-container>
      <ng-template #normalColumns>
        {{column}}
      </ng-template>
    </th>
  </thead>
  <tbody>
    <tr>
      <td *ngFor="let model of columnValues">
        <ng-container >
        {{model}} <input type="checkbox" [(checked)]="checkAll" />
      </ng-container>
      <ng-template #normal>
        {{model}}
      </ng-template>
      </td>
    </tr>
  </tbody>
</table>

In your component:

Create a boolean called checkAll.

Here Stackblitz

2 Comments

That also works. I think that you can use [checked]="checkAll" (one way binding).
I like this approach too. Seem to be learning quite a few useful tips here. Thanks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.