1

I'm learning angularjs and I am having some problems with increasing progress bar during a loop.

I'll explain better. I have the modal with checkbox of all months, like the ones shown on the website below

http://vitalets.github.io/checklist-model/

So, I can choose one or more months to obtain data.

The html code is

 <fieldset>
    <input type="checkbox" ng-model="calendar" ng-change="keepMonths()">All
    <div ng-repeat="month in months">
        <div class="row">
            <input type="checkbox" checklist-model="choose.selected" checklist-value="month"> {{month.name}}
        </div>
    </div>
    <button name="Export" ng-click="exportExcel()" class="upButton">Export</button>
    <div class="demo-section k-content" style="width: 350px;">
        <h4>{{status}}</h4>
        <div kendo-progress-bar="progressBar" k-min="0" k-max="100" ng-model="progress"></div>
    </div>
</fieldset>

If I click in export button it realy works fine, but I want to put a progress bar, because the processing of the months takes a lot of time and I wish the User follow the processing of data, so I try to do this:

   $scope.exportExcel = function () {

    $scope.status = "Processing...";  // it doesn't work
    $scope.$apply($scope.status);  // it doesn't work

    var data = []
    var Increase = $scope.choose.selected.length / 100

    for (var i = 0; i < $scope.choose.selected.length; i++) {
        startDate = new Date("01/01/2015 00:00:00"; //for example
        endDate = new Date("31/01/2015 23:59:59"; //for example

            MUSTService.GetExcel($rootScope.empreendimento, $rootScope.pontoconexao, postohorario, dataInicio, // GetExcel goes to code behind and returns a json (dados) with all data of that month
            function (dados) {
                data = $scope.concatDados(dados, data);  // concatDados is responsible for concatenate all data from months in one variable (data)
            }, null, dataFim);  

        $scope.progress = $scope.progress + Increase; // it doesn't work
        $scope.$apply($scope.progress); // it doesn't work
        $scope.progress = 20; // it doesn't work (for test)
        $scope.$apply($scope.progress); //  it doesn't work (for test)
    }

    // the code below is only responsible for downloading the excel
    var query = 'SELECT NomReduzido AS [Empreendimento], NomCurto AS [Ponto de conexão], DinQuinzeminutos AS [Data/Hora], IFNULL(CodOrigem, \'\') AS Origem, ';
    query = query + ' INTO XLSX("MUST_' + $rootScope.empreendimento.trim() + '_' + decodeURI($rootScope.pontoconexao).trim() + '_' + $rootScope.postohorario.trim() + faltante + '.xlsx" , ? ) FROM ?';
    alasql(query, [opts, data]);

    $scope.progress = 20; // it works
    $scope.$apply($scope.progress); // it works
    $scope.status = "concluded..."; // it works
    $scope.$apply($scope.status);   // it works
}

If I try to Increase the progress bar, it doesn't work. The progress bar only begin to increase after the end of the for loop, and I don't know why. I put some comments in the code to help you to understand.

I tried to put something like that inside of the loop, only for a test, but it doesn't work. However, if I put the same code below outside the loop it works, but what really takes times is the loop part, because of this it's importante to increase there.

   $scope.progress = 20;
   $scope.$apply($scope.progress);

I even tried to put a image with a message "Loading", but the image still appearing only when the for loop ends.

If someone could help me to show a way to increase a progress bar during the loop or even show a image, I will be grateful

  • have you tried printing `$scope.progress` values in for loop? Are they as expected i.e. between 0 to 100 range? Not a NaN or string or something that kendo progress bar doesn't expect? – kachhalimbu Jun 04 '15 at 04:22
  • also I don't think you need to use `$scope.$apply` for updating the kendo progress bar. As it is a `ng-model` for kendo progress bar, it should auto update when you change `$scope.progress` value – kachhalimbu Jun 04 '15 at 04:23
  • btw also check the missing semicolons in your code. For eg. `var data` and `var Instance` declarations – kachhalimbu Jun 04 '15 at 04:25
  • Have you tried $scope.$apply(function () { }); just checking if an error inside your loop is actually preventing the rest to run – n00b Jun 04 '15 at 04:27
  • The problem was because the loop and the prossing were asynchronously. – Tiago Monteiro Jun 04 '15 at 17:01

1 Answers1

0

$scope.progress is being set correctly at the correct times in your code. As long as your script is executing synchronously, though, you will never see a repaint that shows the updates on the progress bar itself. In desktop applications, this issue is generally handled by having a UI thread and a worker thread. The UI thread is basically idle, so it happily repaints when it's informed that the progress has incremented. Leaving aside Web Workers for now, JavaScript is single-threaded, so while you're inside that for loop, it never goes idle and allows a repaint.

If this progress bar is essential, the far-from-trivial answer is to make your for loop asynchronous, using $timeout. Even setting the timeout delay to 0 should work.

More information, and an idea of how to proceed, can be found in the 2nd answer to this Stack Overflow question and the accepted answer on this one.

Community
  • 1
  • 1
Kevin
  • 5,874
  • 3
  • 28
  • 35