2

I have an array of objects containing images with source links. I want to add flag to each image when source link is dead and image can not be loaded. And I have following html code and directive.

Problem is that I can't pass image object directly to the directive to set property on it. I've tried with adding scope to the directive and passing by parameter but it didn't work, so I ended with this ugly approach with tighly coupling directive with outside scope and working on it (annotated lines in the directive source fragment).

Question is: Could it be implemented in a more elegant way by passing image object to directive and without manual $apply() call? Probably yes, but I've tried during weekend and failed.

<!-- AngularJS v. 1.0.8 -->
<ul>
  <li ng-repeat="image in images">
   <div>
      <img ng-src="{{image.srcLarge}}" fallback-src="/assets/fallback.png"/>
      <!--- image comments and other data -->
    </div>
  </li>
<ul>

Directive:

.directive('fallbackSrc', function () {
var fallbackSrc = {
    restrict: 'A',
    link: function postLink(scope, iElement, iAttrs) {
        iElement.bind('error', function() {
            console.log("directive");
            angular.element(this).attr("src", iAttrs.fallbackSrc);
            scope.image.errorPresent = true; // this is problematic
            scope.$apply(); // this is also problematic
        });
    }
};
Tomasz Dziurko
  • 1,668
  • 2
  • 17
  • 21
  • See: http://stackoverflow.com/questions/16310298/if-a-ngsrc-path-resolves-to-a-404-is-there-a-way-to-fallback-to-a-default – oori Mar 10 '14 at 07:30
  • Ok, so I see that question isn't stated clearly enough, so to recap: How could I create this directive in a more elegant way so it doesn't rely on scope.image, but instead could use image object passed as an attribute? – Tomasz Dziurko Mar 10 '14 at 19:42

2 Answers2

0

Try:

.directive('fallbackSrc', function() {
    return {
        restrict: 'A',
        link: function(scope,element,attrs){
            element.on('load', function() {
                 //loaded           
            });
            element.on('error', function() {
                        element.attr('src',attrs.fallbackSrc);
            });
            scope.$watch('ngSrc', function() {
                 //start      
            });      
       }
    }
})

Try:

ng-repeat="image in images" ng-init="image.errorPresent = false"
Whisher
  • 31,320
  • 32
  • 120
  • 201
0

Ok, as I expected it was doable (at least that more ugly issue), friend from work told me to use $eval:

<img ng-src="{{image.srcLarge}}" fallback-src="/assets/fallback.png" imagemodel="image"/>

and

.directive('fallbackSrc', function () {
  var fallbackSrc = {
  restrict: 'A',
  link: function postLink(scope, iElement, iAttrs) {
    iElement.bind('error', function() {
        console.log("directive");
        angular.element(this).attr("src", iAttrs.fallbackSrc);
        var target = scope.$eval(iAttrs.modify);
        target.errorPresent = true; // no longer problematic after $eval call 
        scope.$apply(); // This must be done this way as we are modifying Angular model from the outside of AngularJS scope.
    });
  }
};
Opal
  • 81,889
  • 28
  • 189
  • 210
Tomasz Dziurko
  • 1,668
  • 2
  • 17
  • 21