0

I am displaying users in a table with ng-repeat. One of the columns, "Status" is computed by a function and can return a value 'Active', 'Idle' or 'Locked'. The function uses the current date time to calculate this.

If LastAccess is within the last 5 minutes, the 'Active' status is displayed.

Here is what the table looks like:

enter image description here

Here is the HTML markup:

<tr ng-repeat="user in UserTable.Rows" ng-click="openUser(user.UserID)">
  <td>{{user.FirstName}} {{user.LastName}}</td>
  <td>{{user.Email}}</td>
  <td>{{user.OfficeName}}</td>
  <td>{{user.DeptName}}</td>
  <td>{{user.RoleName}}</td>
  <td><span class="label label-{{getStatus(user)=='Idle'?'default':(getStatus(user)=='Locked'?'danger':'success')}}">{{getStatus(user)}}</span>    </td>
  <td>{{user.LastAccess|timeAgo}}</td>
</tr>

And here is the function for getStatus:

$scope.getStatus = function (usr) {
  if (usr.Locked) return 'Locked';
  if (!usr.LastAccess) return 'Idle';
  var diff = (new Date().getTime() - new Date(usr.LastAccess).getTime()) / 1000;
  console.log(diff);
  if (diff < 300) return 'Active'; else return 'Idle';
}

The problem is that the function is called three times every second for each user (as per the console.log function). I understand why it is called three times (as it is used thrice in the HTML). But can I prevent this from updating every second? Calling the function once a minute would be enough for me. How do I do that?

Is there a better way to do this without creating a filter?

1 Answer 1

2

Don't execute the function in the element. Instead write a directive for the element that shows the Status. Then use $interval inside the directive to call an updater function.

Include the user index in the element as an attribute. Something like this:

<span statusupdater useridx={{UserTable.Rows.indexOf(user)}}></span>

Now the directive is something like this:

myApp.directive('statusupdater', function($interval) {
        return {            
            link: function (scope, element) {

                function update(scope, ele) {

                    var userIdx = ele.attr("useridx");
                    var user = scope.UserTable.Rows[userIdx];

                    //Now process your user and change the style(or class) and html of the 
                    //span element accordingly                    
                };            

                $interval(function(){
                    update(scope, element);
                }, 18000);

        }
 }

Now the update function will executes every 3 minutes per span. It changes the class and the html of each span according to the user status.

Please note that this approach create closures and might not be suitable if you have a large list in a single page. You need to refer to the scope and the element in a different way in that case.

Please also note that you should track the returned promises of the $interval calls and cancel them appropriately if you use paging to display user lists.

Update Also make sure that you add some condition to execute the directive only once if you have automatic updating of the html (every second as said in the question?). Or just disable it iflies within your control.

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

4 Comments

Thanks. But I don't really want to create directives or filters for this. It is used only once in the app and I just wanted a simple solution. The HTML is updating on its own (I guess Angular automatically checks the getStatus method periodically to test if it has changed. I just want to reduce this frequency of automatic updates.
I don't get how angular "automatically" execute anything periodically unless watchers are set and the digestion cycle is invoked by an external process at a specific interval.
Same here. I'm not using any timer anywhere in the app. Angular does this on its own.
If you isolate the code you have excerpted in your question and run it in a controller, the angular will not execute the function periodically. I tested it here. This means the problem is elsewhere in your code.

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.