1

I am trying to update a bootstrap progress bar using angular. The basic idea is taking a textarea and render a canvas image for each textarea line, then package the images in ZIP files, each ZIP file having 100 images. I use JSZip for ZIP file generation.

The problem is that, while the console.log("Progress: " + $scope.progress) gets updated in real time, the progress bar gets updated only after the last ZIP file has been created.

Added a code snippet below, also in fiddle:

http://jsfiddle.net/q1c1qrt4/24/

angular.module('myApp', [])
  .controller('myController', function ($scope, $timeout) {
  // Inicialization
  $scope.progress = 0;
  $scope.strings = ["01","02","03","04","05","06","07","08","09","10",
                   "11","12","13","14","15","16","17","18","19","20",
                   "21","22","23","24","25","26","27","28","29","30",
                   "31","32","33","34","35","36","37","38","39","40",
                   "41","42","43","44","45","46","47","48","49","50",];

  // Render canvas
  var render = function(canvas, value) {
    var context = canvas.getContext('2d');
    canvas.width = canvas.height = 1200;
    context.font="60px Georgia";
    context.fillText(value, 10, 50);
  };
  
  // Download button
  $scope.download = function() {
    $scope.progress = 0;
    var zip = new JSZip();
    var canvas = document.createElement('canvas');
    var total = $scope.strings.length;
    var i = 0;

    // For each line of the textarea
    for (i=0; i<total; i++) {
      // Render canvas
      var text = "" + $scope.strings[i];
      render(canvas, text);
      // Save canvas
      var dataURL = canvas.toDataURL();
      var base64 = dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
      zip.file($scope.strings[i] + ".jpg", base64, {base64: true});
      $scope.progress = (i + 1) * 100 / total;
      console.log("Progress: " + $scope.progress);
      // Every 5 files save ZIP
      if ((i+1) % 5 === 0) {
        var content = zip.generate({type:"blob"});
        saveAs(content, "file" + i + ".zip");
        zip = new JSZip();
      }
    }
    // Last file
    if (i % 5 !== 0) {
      var content = zip.generate({type:"blob"});
      saveAs(content, "file" + total + ".zip");
    }
  };

});
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">

<script src="http://eligrey.com/demos/FileSaver.js/FileSaver.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jszip/2.4.0/jszip.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>

  <body ng-app="myApp">
    <div class="jumbotron" ng-controller="myController">
      <p><textarea>{{strings}}</textarea></p>
      <button type="button" class="btn btn-success" ng-click="download()">Download ZIP <span class="glyphicon glyphicon-cloud-download"></span></button>
      <div class="progress">
        <div class="progress-bar" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" ng-style="{'width': progress + '%'}">{{progress}}%
        </div>
      </div>      
    </div>   
  </body>

I have also tried with ng-value, as well as updating the style="width: 0%;" property, or using ng-style="{'width': progress + '%'}", but it doesn't work either.

In response to Sycomor, I am using UI Bootstrap. I have tried your approach but it doesn't work. I've also tried the standard progressbar. Tried this:

<div class="progress">
    <div class="progress-bar" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" ng-style="{'width': progress + '%'}"></div>
</div>

Tried this:

<div class="progress">
    <div class="progress-bar" ng-style="progressWidth" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100"></div>
</div>

, then:

$timeout(function() {
    $scope.progress = i * 100 / total;
    $scope.progressWidth = {
        'width': $scope.progress + "%"
    };
});

Tried everything with and without the timeout :(

¿Any ideas?

1
  • have you tried "value={{progress}}" ? Also, the standard bootstrap progressbar is somewhat different from what you are using : getbootstrap.com/components/#progress Commented Oct 2, 2014 at 15:50

1 Answer 1

1

Looks like the update to progress is happening outside angular scope/$digest loop, try

$timeout(function(){
   $scope.progress = (i + 1) * 100 / total;
});
Sign up to request clarification or add additional context in comments.

Comments

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.