0

ユーザーのリストを検索して取得する小さな AngularJS アプリと、次に予定されている会議 (次の 8 時間以内に予定されていると仮定) を、現地時間への計算を容易にするために UTC の時間形式で JSON を使用してサーバーから取得します。 . 各ユーザーは、異なるステータス (x 時間までビジー、x 時間まで空き) を持つことができます。

私が達成したいのは、スケジュールされた会議が完了するまでの残り時間または会議が開始されるまでの残り時間で 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);
    };

編集

私は以下のように問題を理解しています。私が苦労しているのは、これを正しく登録する方法です。最大15回以上の別々の時間で単一の目盛りに更新される可能性があるため、迷子になっています。

4

3 に答える 3

1

思ったよりも多くのタイムアウトを登録しています。angular がビューをレンダリングするたびに、新しいタイムアウト ハンドラを登録します。コールバックのカウンターを追加して、カウントが進むのを確認します。

$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);
};

バグを再現したこのプランクを参照してください: 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

于 2013-04-25T01:08:09.030 に答える
1

$scope.calculateTime を再帰的に呼び出しています! また、ng-repeat 中にアイテムのリストを変更しているため、無限ループも発生します。

これはどうですか: http://plnkr.co/edit/0JqK96irV4ETdWZYxO3P?p=preview

ng-repeat に影響しない別の配列を参照するように html を変更しました。

<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);

'_timeLeft' が変更されたことを Angular に知らせるために $scope.$apply() が必要であることに注意してください。これにより、それへのすべての参照が更新されます。

于 2013-04-25T01:10:56.747 に答える
0

$timeoutすべてのビューの更新を呼び出す必要はないと思います。代わりに、コントローラー内で時間をカウントダウンし、view にタイマーを表示させることができます。

http://plnkr.co/edit/OUVdJyllzmVmPC0FhqYF?p=preview

于 2013-04-25T00:29:41.317 に答える