2015-03-13 47 views
2

我试图创建一个指令来对子图像执行缩放。使用ng-repeat嵌入图像,URL来自父控制器中的REST API调用。这里的指令的嵌入:在加载指令后访问子元素图像

而这里的指令模板:

<div> 
    <img image-directive-item ng-src="{{image.url}}" ng-style="{'width': {{image.width}}, 'height': {{image.height}}}" ng-if="image.done" /> 
</div> 

要缩放每个图像,我需要有信息回复:它周围的其他图像的宽度/高度。目前,我试图通过绑定到图像的子指令将此信息传递给父级。下面是我测试的代码:

angular.module("myApp") 
.directive("imageDirective", function() { 
    return { 
     scope: { images: '=images'}, 
     link: function(scope){ 

      for(var i = 0; i < scope.images.length; i++) { 
       console.log(scope.images[i].width, scope.images[i].height); 
      } 

     }, 
     templateUrl: _contextPath + 'static/html/imageDirective.html' 
    }; 
}) 
.directive("imageDirectiveItem", function() { 
    return { 
     link: function(scope, element) { 
      element.bind("load", function(e) { 
       scope.image.width = this.naturalWidth; 
       scope.image.height = this.naturalHeight; 
      }); 
     } 
    }; 
}); 

的图像加载页面上,负载回调可以读取尺寸,但是在控制台输出(从父指令)为“不确定不确定”为所有图像以及有关无法将宽度/高度设置为空值的错误。

我想以这种格式来做,因为我需要按照它们在DOM中出现的顺序处理图像。然而,我正在努力使这两个连接,而不诉诸什么感觉像黑客。有任何想法吗?


由New Dev下面提供的解决方案为我工作。修改了元素如何传递给父指令,以便它从加载回调中传递对象,该回调包含我需要的信息。今天学了一些关于Angular的新内容!

angular.module("myApp") 
.directive("imageDirective", function() { 
    return { 
     scope: { images: '=images'}, 
     controller: function($scope){ 

      var toBeLoaded = $scope.images.length; 

      this.childLoaded = function(childElement) { 
       console.log(childElement.naturalWidth, childElement.naturalHeight); 

       if(--toBeLoaded == 0) { 
        allChildrenLoaded(); 
       } 
      }; 

      function allChildrenLoaded() { 
       console.log("All children loaded."); 
      } 

     }, 
     templateUrl: _contextPath + 'static/html/imageGrid.html' 
    }; 
}) 
.directive("imageDirectiveItem", function() { 
    return { 
     require: "^imageDirective", 
     link: function(scope, element, attrs, imageDirectiveCtrl) { 
      element.bind("load", function() { 
       var e = this; 
       scope.$apply(function() { 
        imageDirectiveCtrl.childLoaded(e); 
       }); 
      }); 
     } 
    }; 
}); 

和控制台输出:

414 415 
507 338 
366 468 
432 395 
500 354 
507 338 
414 414 
478 358 
507 338 
All children loaded. 

回答

2

为什么要打印undefined undefined的原因是因为没有图片都在,你正在做你的for循环的时间被加载。

如果您需要“处理”(如您所说)父级中的结果,那么设置范围暴露对象上的值可能不是最佳方法。你怎么知道它已经完成加载,例如?你怎么知道没有昂贵的深$watch有什么改变?

我认为更好的方法是公开一个子指令可以调用的API。这是通过在父母的控制器上暴露一个功能并在孩子身上使用require: "^imageDirective"来完成的。

.directive("imageDirective", function(){ 
    return { 
    // .. whatever you currently have 
    controller: function($scope){ 
     var toBeLoaded = 0; 
     this.registerChild = function(childElem){ 
     toBeLoaded++; 
     }; 

     this.childLoaded = function(childElem){ 
     toBeLoaded--; 
     // do whatever processing you need 
     }; 
    } 
    } 
}) 
.directive("imageDirectiveItem", function(){ 
    return { 
    require: "^imageDirective", 
    link: function(scope, element, attrs, imageDirectiveCtrl){ 
     imageDirectiveCtrl.registerChild(element); 

     element.bind("load", function(){ 
      scope.$apply(function(){ 
      imageDirectiveCtrl.childLoaded(element); 
      }) 
     }) 
    } 
    } 
} 
+1

你是伟大的先生:)好的方法 – 2015-03-13 14:49:54

+0

这太棒了!我修改了一些代码以适合我的需要(访问_this_内部的bind回调来访问维度参数,正如我原本想做的那样)。谢谢! – karmat 2015-03-13 14:56:27

+0

不错的解决方案... – 2015-03-13 15:15:24

0

如果您使用的是最新的浏览器(IE> = 11),你可以尝试MutationObserver

试试这个在imageDirective的链接功能。

var observer = new MutationObserver(function(mutations) { 
     mutations.forEach(function(mutation) { 
      var target = mutation.addedNodes && mutation.addNodes[0], 
       targetScope; 
      if (target) { 
       target = angular.element(target); 
       targetScope = target.scope(); 
       console.log(targetScope.width, targetScope.height) 
      } 
     });  
}); 

var config = {childList: true}; 

observer.observe(element[0], config);