1

It is possible in Angular to have a callback for finished ng-repeat update?

I can successfuly catch the initial rendering by using a directive and the $last property, but its not working for view update.

I have got a big list and the filtering takes time, I want to show a sppiner when Angular is sorting the view, so i am looking for a way to catch the moment and hide the spinner.

The application behavior should be: 1.click on sort button 2.spinner should appear 3.angular filtering / data will be ordered 4.finished order script 5.ordered data appears 6.spinner hides

thanks.

1 Answers1

1

After looking at some of the examples in the link that Pankaj Parkar provided I threw together a plunker as a demo of a possible implementation. I don't think it's completely optimal and you should look into a better solution but you might find it to be a helpful starting point if you are still working on this. It's not pretty but it sounds like it might be the sort of thing you're aiming for.

HTML

<!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script data-require="angular.js@1.4.x" src="https://code.angularjs.org/1.4.2/angular.js" data-semver="1.4.2"></script>
    <script src="app.js"></script>
  </head>

  <body ng-controller="MainCtrl">

    <button ng-click="populateBigTable()">Populate Table</button>

    <div class="table-wrapper">
      <div class="overlay" ng-hide="hideOverlay">Loading</div>
      <table>
        <thead>
          <tr>
            <th>id</th>
            <th>item</th>
          </tr>
        </thead>
        <tbody>
          <tr ng-hide="hidePlaceholder">
            <td colspan=2 class="placeholder">(no data here yet..)</td>
          </tr>
          <tr ng-repeat="some in data" on-complete="done()" >
            <td>{{some.id}}</td>
            <td>{{some.item}}</td>
          </tr>
        </tbody>
      </table>
    </div>

  </body>

</html>

app.js

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope, $timeout) {

  $scope.hideOverlay      = true;
  $scope.hidePlaceholder  = false;

  $scope.done = function(){
    $scope.hideOverlay = true;
  }

  $scope.data = [];

  $scope.populateBigTable = function(){

    var data = [];

    $scope.hideOverlay      = false;
    $scope.hidePlaceholder  = true;

    // HACK
    // needed so that angular has time to hide elements
    // no ideal but does the job
    $timeout(function(){
      for(var i = 0; i < 30000; i++){
        data.push({
          id: i,
          item: 'some item'
        });
      }

      $scope.data = data;
    }, 25)

  }

});


app.directive('onComplete', function(){
  return {

    restrict: 'AE',

    link: function(scope, element, attrs){

      if(scope.$last){

        scope.$eval(attrs.onComplete);

      }
    }

  }
});

CSS

.table-wrapper {
  position:relative;
  width: 100%;
}

table {
  width: 100%;
  table-layout: fixed;
  min-height: 500px;
}

table tr td {
  border: 1px solid black;

}

.placeholder {
  text-align: center;
}

.overlay{
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 10;
  background-color: rgba(0,0,0,0.5); /*dim the background*/
}
Matt Herbstritt
  • 4,754
  • 4
  • 25
  • 31