2013-04-24 26 views
0

我有一個小型的AngularJS應用程序,它可以搜索並檢索用戶列表以及他們下一次安排的會議(假設一個會在接下來的8小時內安排)格式爲UTC,便於計算到當地時間。每個用戶可以具有不同的狀態(直到x時間爲止,直到x時爲止)。AngularJS在ng-repeat中的倒計時

我想完成的是能夠用剩餘的時間更新DOM,直到會議安排完成或剩下一段時間,直到會議開始。我有一些代碼工作,但因爲我顯然沒有正確地做到這一點,只有在結果集中的幾個條目,它使瀏覽器幾乎停滯不前。任何建議,將不勝感激!

我當前的代碼包括以下代碼段:

[首頁]

<tr ng-repeat="item in pagedItems[currentPage-1] | orderBy:sortingOrder:reverse" ng-class="{success:item._freeBusy=='Free', error:item._freeBusy=='Busy'}"> 
     <td>{{item._firstName}}</td> 
     <td>{{item._lastName}}</td> 
     <td>{{item._facilityName}}</td> 
     <td>{{item._extension}}</td> 
     <td>{{item._description}}</td> 
     <td><a ng-hide="!item._extension" ng-click="dial(item)">Dial</a></td> 
     <td><button class="btn btn-primary" ng-click="openDetails(item)">Details</button></td> 
     <td>{{item._freeBusy}} {{item._timeLeft}} {{calculateTime(item._freeBusyTime,$index)}}</td> 
</tr> 

[控制器]

 $scope.timeUntil = function(s) { 
     function isoToObj(s) { 
      var b = s.split(/[-T+:]/i); 
      return new Date(Date.UTC(b[0], --b[1], b[2], b[3], b[4], b[5])); 
     } 
     // Utility to add leading zero 
     function z(n) { 
      return (n < 10 ? '0' : '') + n; 
     } 
     // Convert string to date object 
     var d = isoToObj(s); 
     var diff = d - new Date(); 
     // Allow for previous times 
     var sign = diff < 0 ? '-' : ''; 
     diff = Math.abs(diff); 
     // Get time components 
     var hours = diff/3.6e6 | 0; 
     var mins = diff % 3.6e6/6e4 | 0; 
     var secs = Math.round(diff % 6e4/1e3); 
     // Return formatted string 
     return sign + z(hours) + ' Hours ' + z(mins) + ' Min' + ':' + z(secs);// + ':' + z(secs) 
    } 

    $scope.calculateTime = function(s, idx) { 
     timeoutID = $timeout(function() { 
      $scope.items[idx]._timeLeft = $scope.timeUntil(s); 
      $scope.calculateTime(s, idx); 
     }, 1000); 
    }; 

編輯

我理解的問題,如下面提到,我正在掙扎着w第i個是如何正確地註冊這個。因爲它可能會多達15次不同的時間更新爲單個刻度,這就是我迷路的地方。

+0

看到我更新的答案 – Sylvain 2013-04-25 01:47:02

回答

1

比你以爲你是註冊方式更爲超時。每次角度呈現您的視圖,您註冊新的超時處理程序。添加您的回調的櫃檯,並觀看數去:

$scope.called = 0; 

$scope.calculateTime = function(s, idx) { 
    timeoutID = $timeout(function() { 
     $scope.items[idx]._timeLeft = $scope.timeUntil(s); 
     $scope.calculateTime(s, idx); 
     console.log(++$scope.called); 
    }, 1000); 
}; 

看到這個普拉克,我轉載的bug:http://plnkr.co/edit/qJ4zDl6gc5C7Edg0T0gB。運行它並觀看櫃檯。

爲什麼要在渲染週期中更新_timeLeft?爲什麼不這樣做:

$scope.called = 0; 

setInterval(function() { 
    angular.forEach($scope.items, function function_name(item) { 
    item._timeLeft = $scope.timeUntil(item._freeBusyTime); 
    }); 
    console.log(++$scope.called); 
    $scope.$apply(); 
}, 1000); 

見新普拉克:http://plnkr.co/edit/rVJ6p4VXDQvt7rjT6eka

+0

這個工作對我來說更好,因爲它是一個過濾列表,現在與特定元素與跟蹤另一個陣列在頁面的變化,無需額外的功能將不會更新到正確的記錄相關的部分。 – Brian 2013-04-25 15:01:07

1

您遞歸調用$ scope.calculateTime!而且你正在修改ng-repeat期間的項目列表,這也會導致無限循環。

如何:http://plnkr.co/edit/0JqK96irV4ETdWZYxO3P?p=preview

改變了HTML來指代一個單獨的數組不影響NG-重複:

<td>in {{_timeLeft[$index]}}</td> 

被更新如下:

$scope._timeLeft = []; 

var intervalID = window.setInterval(function() { 
    for (var i=0; i<$scope.items.length; i++) { 
     $scope._timeLeft[i] = $scope.timeUntil($scope.items[i]._freeBusyTime); 
    } 
    $scope.$apply(); 
}, 1000); 

請注意,需要$ scope。$ apply()才能讓Angular知道'_timeLeft'已被修改,它會更新對它的所有引用。

+0

太棒了!謝謝,我現在一直在撓頭... – Brian 2013-04-25 03:27:01