Search code examples
angularangular-templateng-container

Bind to Template Reference Variable inside <ng-container> angular


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


Solution

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