0

I have some data that i am showing using ngFor directive in a table. I have checkbox in the last column and i want it to select only the row that will be selected but not the other rows. Here is my code

HTML Code

<div *ngIf="!admin">
          <div class="row clearfix">
            <div class="col-sm-12">
              <input type="checkbox" name="permission12" value="" (change)="isSelected = !isSelected" class="filled-in" id="permission12" (click)="chosen(listSupportAdminSchools.items)" />
              <label for="permission12">: Select All</label>
              <table class="table-bordered table-striped" style="width:100%">
                <thead>
                  <tr>
                    <th>Name</th>
                    <th>Registration Number</th>
                    <th>Enrollment Type</th>
                    <th>Entity Type</th>
                    <th>Location</th>
                    <th>IsActive</th>
                    <th>Select</th>
                  </tr>
                </thead>
                <tbody>
                  <tr *ngFor="let x of listSupportAdminSchools.items;">
                    <td>{{x.name}}</td>
                    <td>{{x.registrationNumber}}</td>
                    <td>{{x.educationType}}</td>
                    <td>{{x.administrativeType}}</td>
                    <td>{{x.county}}
                      <span>,</span>{{x.city}}
                      <span>,</span>{{x.district}}</td>
                    <td></td>
                    <td style="text-align: center">
               <!--       <button (click)="onClick()" class="btn btn-primary waves-effect">Select</button>   -->
                      <input type="checkbox" name="permission13" value="" [(ngModel)] = "isSelected" class="validate form-control" id="permission13" (click)="chosen()" />
                      <label for="permission13">: Select</label>
                    </td>
                  </tr>
                </tbody>
              </table>
            </div>
          </div>
        </div>

while in my .ts file i have a isSelected boolean variable set to false.

Whenever i click on one checkbox in the row it select other one too. But the select all checkbox is working just fine

CsgUy
  • 27
  • 7

1 Answers1

1

This issue is not caused by angular, but rather by how HTML handles the label's for attribute. The browser looks for the first element with a matching id property and sends all clicks there.

To fix this, you need to give each checkbox a unique id:

<div *ngIf="!admin">
  <div class="row clearfix">
    <div class="col-sm-12">
      <input type="checkbox" name="permission12" value="" (change)="isSelected = !isSelected" class="filled-in" id="permission12" (click)="chosen(listSupportAdminSchools.items)" />
      <label for="permission12">: Select All</label>
      <table class="table-bordered table-striped" style="width:100%">
        <thead>
          <tr>
            <th>Name</th>
            <th>Registration Number</th>
            <th>Enrollment Type</th>
            <th>Entity Type</th>
            <th>Location</th>
            <th>IsActive</th>
            <th>Select</th>
          </tr>
        </thead>
        <tbody>
          <tr *ngFor="let x of listSupportAdminSchools.items; let i = index">
            <td>{{x.name}}</td>
            <td>{{x.registrationNumber}}</td>
            <td>{{x.educationType}}</td>
            <td>{{x.administrativeType}}</td>
            <td>{{x.county}}
              <span>,</span>{{x.city}}
              <span>,</span>{{x.district}}</td>
            <td></td>
            <td style="text-align: center">
       <!--       <button (click)="onClick()" class="btn btn-primary waves-effect">Select</button>   -->
              <input type="checkbox" [name]="'permission13' + 1" value="" [(ngModel)] = "x.isSelected" class="validate form-control" [id]="'permission13' + i" />
              <label [for]="'permission13' + i">: Select</label>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
</div>

Changes:

First, we use modify the *ngFor to track the index for us

*ngFor="let x of listSupportAdminSchools.items; let i = index"

Then, we do some simple string concatination to ensure each checkbox id is unique

[id]="'permission13' + i"

Finally, we modify the label for in the same way

[for]="'permission13' + i"

Notes:

  • By adding the [] brackets around the attribute, we make angular process this as Javascript. This lets us use the + operator.
  • Since it is now Javascript we need to add '' around permission13 so it is treated as a string, rather than a variable name
  • This is the simplest way to accomplish this, you could also generate these value from other unique properties of your *ngFor object, eg [id]="'permission13' + x.objectId"

(OBSELETE) Update for single row selected:

Update checkbox binding:

[ngModel] = "selectedRow === x" (ngModelChange)="selectedRow = x"

You will need a property in the model selectedRow. When a checkbox is clicked, it sets this value. Each checkbox is now bound to an expression, so only one checkbox should appear checked at a time.

Vlad274
  • 6,514
  • 2
  • 32
  • 44
  • but since the checkboxes are being created due to ngFor directive, how can i give each checkbox a different value with that loop? – CsgUy Jul 11 '18 at 15:22
  • You can see in the answer I posted, but I'll add a callout for the specific changes I made – Vlad274 Jul 11 '18 at 15:23
  • 1
    this won't work either because all checkbox are bind to isSelected property. changing name and for to be unique is half solution – Nitin Walia Jul 11 '18 at 15:25
  • @CsgUy, Nitin raises a very good point that will also cause a problem. The generated checkboxes are all pointing to the same NgModel value, so will all be the same. I assume this is just a type, and you meant to have something like `x.isSelected`. Make sure you update that piece as well – Vlad274 Jul 11 '18 at 15:33
  • @Vlad274 no its still not working, one checkbox is triggering the one again – CsgUy Jul 11 '18 at 15:34
  • no isSelected is not any typo error. I have isSelected property set to false in .ts file – CsgUy Jul 11 '18 at 15:35
  • @CsgUy If you have multiple checkboxes pointing to the same model value, then they must all have the same value. If that's not your intent, then you need to have different model values for them to bind to – Vlad274 Jul 11 '18 at 15:36
  • @CsgUy I apologize, I misunderstood part of your intent. I've updated the code to have a single checkbox appear as selected – Vlad274 Jul 11 '18 at 15:41
  • they are all going to bind to different values in rows. Every checkbox will be pointing towards a specific tenant name. But how can i bind them to different model? i have right now binded it to isSelected property because i want the select all box to select all checkboxes – CsgUy Jul 11 '18 at 15:43
  • @CsgUy It's going to depend on where you want to store those bound values. The easiest place (IMO) would be to be on a property of `x`, otherwise it'll be a pain to link them up. Regardless, since each rows checkbox can be in a different state you can't bind them all to isSelected. To get the "select all" behavior you describe, you should put a click event on that checkbox and have it go change all the bound values (in the easy case I mentioned, this would be loop over everything and set the value to true eg `x.isSelected= true`) – Vlad274 Jul 11 '18 at 15:48
  • Thanks alot for you help :) – CsgUy Jul 11 '18 at 15:53