1

This is my code:

TS:

  selRow: boolean = false;

HTML:

<tr *ngFor="let user of users" [ngClass]="selRow ? 'selRow' : ''">
  <td class="checkbox-field"><input type="checkbox" (change)="selRow = !selRow" /></td>
  <td class="user-field"> <img [src]="user.userPicture" alt="">
      {{ user.firstName }} {{ user.lastName }}</td>
  <td class="company-field">{{ getCompany(user.companyId) }}</td>
  <td class="email-field">{{ user.email }}</td>
  <td class="roles-field">{{ user.permissionRoles }}</td>
  <td class="edit-field">Edit</td>
  <td class="delete-field"><i class="fas fa-trash-alt"></i></td>
</tr>

CSS:

.selRow {
   background-color: var(--el-lightblue);
}

.selRow .delete-field {
   color: var(--el-red);
}

I'd like the above code to change only the checked row by the checkbox, yet it changes the CSS of all rows. Does anyone know how I can fix this? Here is the example:

Before selected: img-1

After selected: img-2

4
  • It looks like you are using a single variable selRow to indicate the state of ALL rows. You need to store the state per row. The simplest that I can think of is to create a dictionary mapping based on the index. Commented Jun 6, 2022 at 11:57
  • I've deleted my original answer. Can you please tell me how selRow is used in your .ts? Commented Jun 6, 2022 at 12:00
  • As @RobinDeSchepper said, it is a boolean. I'll try the dictionary mapping option if nothing else comes up. Commented Jun 6, 2022 at 12:04
  • You can extend your ngFor statement: *ngFor="let user of users; let i = index" to get a number for each row. Commented Jun 6, 2022 at 12:06

3 Answers 3

2

Your condition of [ngClass] is wrong, as it is true for all of the rows.

if you need to highlight one row at a time, you can save the row index, instead of using selRow property.

Like This:

in TS

class Component {
   selectedUserIndex: number = null;

   onToggleUser(userInded: number) {
       // unselect the selected row, when the click was on the selected row
       if(userInded === this.selectedUserIndex) {
          this.selectedUserIndex = null;
          return;
       }

       this.selectedUserIndex = userInded;
   }
}

in Template

<tr *ngFor="let user of users; let userInded = index" [ngClass]="userInded ==  selectedUserIndex ? 'selRow' : ''">
  <td class="checkbox-field"><input type="checkbox" (change)="onToggleUser(userInded)" /></td>
  <td class="user-field"> <img [src]="user.userPicture" alt="">
      {{ user.firstName }} {{ user.lastName }}</td>
  <td class="company-field">{{ getCompany(user.companyId) }}</td>
  <td class="email-field">{{ user.email }}</td>
  <td class="roles-field">{{ user.permissionRoles }}</td>
  <td class="edit-field">Edit</td>
  <td class="delete-field"><i class="fas fa-trash-alt"></i></td>
</tr>

In the case of multiselection rows: in TS

class Component {
   selectedUsers: { [key: number]?: boolean } = {};

   onToggleUser(userInded: number) {
       // unselect the selected row, when the click was on the selected row
       if(this.selectedUsers[userInded]) {
         this.selectedUsers[userInded] = false;
          return;
       }

       this.selectedUsers[userInded] = true;
   }
}

in Template

<tr *ngFor="let user of users; let userInded = index" [ngClass]="selectedUsers[userInded] ? 'selRow' : ''">
  <td class="checkbox-field"><input type="checkbox" (change)="onToggleUser(userInded)" /></td>
  <td class="user-field"> <img [src]="user.userPicture" alt="">
      {{ user.firstName }} {{ user.lastName }}</td>
  <td class="company-field">{{ getCompany(user.companyId) }}</td>
  <td class="email-field">{{ user.email }}</td>
  <td class="roles-field">{{ user.permissionRoles }}</td>
  <td class="edit-field">Edit</td>
  <td class="delete-field"><i class="fas fa-trash-alt"></i></td>
</tr>
Sign up to request clarification or add additional context in comments.

Comments

1

From your code, you are sharing selRow for each row, hence when you tick the checkbox in a row, other rows' checkboxes will also automatically checked.

Instead, what you need are:

  1. selRows: An array to store selected index.
  2. toggleSelectedRows: An method to add/remove the index from selRows.
  3. isSelectedRow: Check whether the index is added in selRows.
selRows: number[] = [];

toggleSelectedRows(i: number) {
  let index = this.selRows.findIndex((x) => x == i);

  if (index == -1) this.selRows.push(i);
  else this.selRows.splice(index, 1);
}

isSelectedRow(i: number) {
  return this.selRows.findIndex((x) => x == i) > -1;
}
<tr
  *ngFor="let user of users; let i = index"
  [ngClass]="isSelectedRow(i) ? 'selRow' : ''"
>
  <td class="checkbox-field">
    <input type="checkbox" (change)="toggleSelectedRows(i)" />
  </td>
  
  ...
</tr>

Sample StackBlitz Demo

Comments

-2

From the code that you've shown, I'm guessing that "selRow" is a boolean variable in your component.

Since there's always a single instance of that variable, it affects all rows.

You need either a separate variable for each row (perhaps a property in the 'user" if more than one can be selected, or if only one can be selected at a time, a variable that holds the currently selected user.

1 Comment

Yah! I was already expecting that to be the issue, I just never thought of any other way on how to do it. But thx for the answer!

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.