0

I have the following needs:

1) I'd like to be able to intercept calls to img ng-src via my http interceptor. Given that ng-src does not get routed to http interceptors, I am using this http-src directive https://stackoverflow.com/a/29606436/1361529

2) The problem however is that this directive only works once - it replaces the "src" attribute with the image, so the image only loads once and does not change.

What I mean is my template has the following code:

<span ng-repeat="monitor in MontageMonitors>
<img id="img-$index" http-src="{{LoginData.streamingurl}}/nph-zms?mode=single&monitor={{monitor.Monitor.Id}}&scale={{LoginData.montageQuality}}{{$root.authSession}}&rand={{$root.rand}}" ng-click="openModal(monitor.Monitor.Id, monitor.Monitor.Controllable, monitor.Monitor.ControlId)" />

</span>

This image is reloaded every 1 second via a timer in my code, but since the http-src directive essentially replaces the src attribute with an inline image, it doesn't update.

How do I solve this?

thanks

Community
  • 1
  • 1
user1361529
  • 2,667
  • 29
  • 61

1 Answers1

3

In your custom http-src directive's link function, you would need to $observe the attribute and make your $http call each time it changes.

Something like this (based on the code from the SO answer you linked to):

angular.module('myApp', [])
  .directive('httpSrc', httpSrcDirective);

httpSrcDirective.$inject = ['$http'];

function httpSrcDirective($http) {
  return {
    link: postLink,
    restrict: 'A'
  };

  function postLink(scope, element, attrs) {
    var requestConfig = {
      method: 'GET',
      responseType: 'arraybuffer',
      cache: 'true'
    };

    function base64Img(data) {
      var arr = new Uint8Array(data);
      var raw = '';
      var i, j, subArray, chunk = 5000;
      for (i = 0, j = arr.length; i < j; i += chunk) {
        subArray = arr.subarray(i, i + chunk);
        raw += String.fromCharCode.apply(null, subArray);
      }
      return btoa(raw);
    };

    attrs.$observe('httpSrc', function(newValue) {
      requestConfig.url = newValue;
      $http(requestConfig)
        .then(function(data) {
          attrs.$set('src', "data:image/jpeg;base64," + base64Img(data));
        });
    });
  }
}
Shaun Scovil
  • 3,905
  • 5
  • 39
  • 58
  • can you please take a look at this gist and let me know if you see anything out of order? httpSrc is the directive you posted, httpSrcOld is the old directive. When I switch to the new directive, the image does not load. When I switch to the old directive the image does load (albeit only once). Thank you. https://gist.github.com/pliablepixels/5862dacdfdbcc8aa6b33 – user1361529 Jan 23 '16 at 12:06
  • You may need to change requestConfig.url = newValue; to requestConfig.url = scope.$eval(newValue); – Shaun Scovil Jan 23 '16 at 12:17
  • So the problem was $http.then - I had to change it to $http.success – user1361529 Jan 23 '16 at 12:30
  • You must be using an old version of Angular; $http().success is deprecated. – Shaun Scovil Jan 23 '16 at 12:31
  • Thank you I did have a related problem -- in some of the the http queries, the server keeps sending data over the url - kind of like a mjpeg streaming situation. In this new code, it only loads once - how do I add a functionality to the directive to keep displaying new data if the server keeps streaming it ? – user1361529 Jan 23 '16 at 12:33
  • This might help? http://stackoverflow.com/questions/16791295/how-to-read-binary-data-in-angularjs-in-an-arraybuffer – Shaun Scovil Jan 23 '16 at 12:39
  • Thanks - I think that link shows how to get binary data - Im struggling with how to keep loading data the server sends (many image frames) in the http-src directive. – user1361529 Jan 23 '16 at 12:43
  • uh-oh, I have a problem already. When I use this code in a situation when the server keeps streaming images, the ".success" never gets called - gak. How do I handle that? – user1361529 Jan 23 '16 at 12:47