Angular JS and Directive Link and $timeout

50,974

Solution 1

In your code your comment says 'show only one "pass"'. Timeout only executes one time, after the specified, delay.

Perhaps you want setInterval (if you're pre angular 1.2)/ $interval (new to 1.2) which sets up a recurring call. Here's the setInterval version:

var timeout = setInterval(function(){
    // do stuff
    $scope.$apply();
}, 2000); 

I included $apply as a reminder that since this is an external jQuery call you need to tell angular to update the DOM (if you make any appropriate changes). ($timeout being an angular version automatically updates the DOM)

Solution 2

You can inject dependencies to the directive like in other modules:

.directive('myDirective', ['$timeout', function($timeout) {
   return {
        ...
        link: function($scope, element){
            //use $timeout
        }
    };
}]);

Solution 3

Not sure if I got your doubt here, but $timeout is pretty much the same thing as javascript plain setTimeout function, and it is supposed run only once, as opposed as setInterval.

If you're using Angular 1.2.0, change $timeout service per $interval. If otherwise you're on 1.0 version, you can make it recursive:

var timeout;
var update = function() {
  // clear previous interval
  timeout && timeout();
  timeout = $timeout(function() {
    // drawSomething(...);
    update();
  }, 2000);
}
Share:
50,974
Andrea Mucci
Author by

Andrea Mucci

Updated on February 09, 2020

Comments

  • Andrea Mucci
    Andrea Mucci over 4 years

    i have a problem with a very basic example with AngularJS and directives. I want to create a directive that show a webcam image with webrtc. My code show the stream perfectly but if i add a timeout ( for example to refresh a canvas ) the $timeout don't work this is the code:

    wtffDirectives.directive('scannerGun',function($timeout){
        return {
            restrict: 'E',
            template: '<div>' +
                '<video ng-hide="videoStatus"></video>' +
                '<canvas id="canvas-source"></canvas>' +               
                '</div>',
            replace: true,
            transclude: true,
            scope: false,
            link: function postLink($scope, element){
               $scope.canvasStatus = true;
               $scope.videoStatus = false;
    
               width = element.width = 320;
               height = element.height = 0;
    
               /* this method draw the webcam image into a canvas */
               var drawVideoCanvas = function(){
                  sourceContext.drawImage(vid,0,0, vid.width, vid.height);
               };
    
               /* start the timeout that take a screenshot and draw the source canvas */
               var update = function(){
                  var timeout = $timeout(function(){
                    console.log("pass"); //the console log show only one "pass"
                    //drawVideoCanvas();
                  }, 2000);
               };
    
               /* this work perfectly and reproduct into the video tag the webcam */
               var onSuccess = function onSuccess(stream) {
                  // Firefox supports a src object
                  if (navigator.mozGetUserMedia) {
                     vid.mozSrcObject = stream;
                  } else {
                     var vendorURL = window.URL || window.webkitURL;
                     vid.src = vendorURL.createObjectURL(stream);
                  }
                  /* Start playing the video to show the stream from the webcam*/
                  vid.play();
                  update();
               };
    
               var onFailure = function onFailure(err) {
    
                  if (console && console.log) {
                    console.log('The following error occured: ', err);
                  }
                  return;
               };
    
               var vid = element.find('video')[0];
               var sourceCanvas = element.find('canvas')[0];
               var sourceContext = sourceCanvas.getContext('2d');
    
               height = (vid.videoHeight / ((vid.videoWidth/width))) || 250;
               vid.setAttribute('width', width);
               vid.setAttribute('height', height);
    
               navigator.getMedia (
                  // ask only for video
                  {
                    video: true,
                    audio: false
                  },
                  onSuccess,
                  onFailure
               );
             }
           }
        });
    

    What is the problem? why the $timeout don't work in this conditions? and finally have a solution?

    thank's in advance