0

I have a HTML table row element (tr) with an ng-class associated to it. The 'active' class is a CSS style that highlights the table row. There is a condition (selRole==role) to indicate that the selected role must be highlighted.

#rolesTable tr.active td {
color: #ffffff;
background-color: #2a9fd6;
}


<tr ng-class="{'active':selRole==role}" ng-click="setCurrentRole(role)" ng-repeat="role in roles">
   <td>{{ role.Name }}</td>
</tr>

$scope.setCurrentRole = function (role) {
        $scope.selRole = role;
        $scope.permissions = role.Permissions;
        $scope.selPermission = null;
        $scope.selRoleIndex = $scope.roles.indexOf(role);
    }

Right now when I click on a row, it changes color to indicate I selected it.

The problem I have is that sometimes I need to refresh the list of roles in the table. The selRole property keeps it value but when I refresh the list I lose the highlight.

Even when I force the code to execute the function setCurrentRole, it does not automatically highlight. I explicitly need to click on it to highlight it.

I need for the selected role to remain highlighted, even when I refresh the list. I don't know how to do this in AngularJS.

Ray
  • 4,679
  • 10
  • 46
  • 92
  • you can use ng-class="{true: 'active'}[selRole==role]" – Praveen Soni Jan 06 '19 at 07:16
  • after refreshing, you need to call the `setCurrentRole` again (as you tried). But do you pass a role as input of this function when you call it after the refresh? Try to call it as `$scope.setCurrentRole($scope.roles[0])` after the refresh, and check if the first role will be highlighted after refreshing roles – quirimmo Jan 06 '19 at 07:39

1 Answers1

0

EDIT: The problem actually appears to be using == to check for equality between 2 objects in javascript. This operator does not do that (see How to determine equality for two JavaScript objects?).

What is happening above is when your list first loads, you get List1 of items, and select a specific object in List1, lets say List1Item, to be $scope.selRole. Since these two objects are the same instance, $scope.selRole == List1Item will evaluate to TRUE and your ng class will work.

When you 'refresh' the list of items, I assume you are creating new objects for List2. Now, even if List1Item matches all the properties of List2Item, $scope.selRole == List2Item will always be false, as they are not the same object, and ng-class will not work until $scope.selRole becomes List2Item.

There are two solutions here:

  1. If you have a unique ID on each role, you can use ng-class="{'active':selRole.Id == role.Id}"

  2. If you don't have a unique ID, you can implement a $scope.roleIsSelected(role) scope function, and use that to check for equality. Then ng-class="{'active':roleIsSelected(role)}" will evaluate corretly.

Mattkwish
  • 753
  • 7
  • 16
  • I tried this solution but I still get the same old behavior. The role is not being highlighted. I am not sure what you mean by "trigger a new digest". I read a little about it, but I'm wondering if that one line is all that is needed? – Ray Jan 06 '19 at 02:26
  • In AngularJS the "$scope" is just a massive dictionary. Every time a value in the dictionary changes, a "digest" occurs. This digest updates anything in the view bounded to each scope value. This may be directives, watches, etc. Sometimes, you may update a value in the scope and a digest may not occur. In that case you need to trigger a digest, and the safest way to do that is `$applyAsync()`, or `$evalAsync()`. My guess above was that what was happening is the value updated but the digest didn't occur – Mattkwish Jan 06 '19 at 17:54
  • @Ray Upon looking closer, I believe the problem is that you are trying to compare two objects in Javascript. Two objects instantiated differently will never be equal even if all the properties match. When you 'refresh' the list of roles, are you getting/creating new objects? If that's the case then `$scope.$selRole` is not equal to the new object that may have all properties equal to your old `$scope.selRole`. Change your code to check an ID on each `role` object for equality, or implement a function to check if two roles are equal, rather than a direct comparison using `==`. – Mattkwish Jan 06 '19 at 18:00
  • @Ray did this fix your problem? – Mattkwish Jan 15 '19 at 03:25
  • 1
    I did not have the time to apply this solution yet. I will update asap. – Ray Jan 15 '19 at 15:50