115

I've got a seemingly simple problem with no apparent (by reading the Angular JS docs) solution.

I have got an Angular JS directive that does some calculations based on other DOM elements' height to define the height of a container in the DOM.

Something similar to this is going on inside the directive:

return function(scope, element, attrs) {
    $('.main').height( $('.site-header').height() -  $('.site-footer').height() );
}

The issue is that when the directive runs, $('site-header') cannot be found, returning an empty array instead of the jQuery wrapped DOM element I need.

Is there a callback that I can use within my directive that only runs after the DOM has been loaded and I can access other DOM elements via the normal jQuery selector style queries?

4

6 回答 6

137

这取决于您的 $('site-header') 是如何构造的。

您可以尝试使用0 延迟的$timeout 。就像是:

return function(scope, element, attrs) {
    $timeout(function(){
        $('.main').height( $('.site-header').height() -  $('.site-footer').height() );
    });        
}

解释它是如何工作的:

不要忘记注入$timeout你的指令:

.directive('sticky', function($timeout)
于 2012-09-03T06:41:58.090 回答
44

这是我的做法:

app.directive('example', function() {

    return function(scope, element, attrs) {
        angular.element(document).ready(function() {
                //MANIPULATE THE DOM
        });
    };

});
于 2014-05-06T21:55:14.290 回答
37

可能作者不再需要我的答案了。尽管如此,为了完整起见,我觉得其他用户可能会觉得它很有用。最好和最简单的解决方案是$(window).load()在返回函数的主体内部使用。(或者您可以使用document.ready。这真的取决于您是否需要所有图像)。

$timeout我的拙见,使用是一个非常薄弱的​​选择,在某些情况下可能会失败。

这是我要使用的完整代码:

.directive('directiveExample', function(){
   return {
       restrict: 'A',
       link: function($scope, $elem, attrs){

           $(window).load(function() {
               //...JS here...
           });
       }
   }
});
于 2014-01-07T05:54:03.630 回答
8

有一个ngcontentloaded事件,我想你可以使用它

.directive('directiveExample', function(){
   return {
       restrict: 'A',
       link: function(scope, elem, attrs){

                $$window = $ $window


                init = function(){
                    contentHeight = elem.outerHeight()
                    //do the things
                }

                $$window.on('ngcontentloaded',init)

       }
   }
});
于 2014-01-29T02:33:15.347 回答
5

如果由于外部资源而无法使用 $timeout 并且由于特定的时间问题而无法使用指令,请使用广播。

$scope.$broadcast("variable_name_here");在所需的外部资源或长时间运行的控制器/指令完成后添加。

然后在加载外部资源后添加以下内容。

$scope.$on("variable_name_here", function(){ 
   // DOM manipulation here
   jQuery('selector').height(); 
}

例如在延迟 HTTP 请求的承诺中。

MyHttpService.then(function(data){
   $scope.MyHttpReturnedImage = data.image;
   $scope.$broadcast("imageLoaded");
});

$scope.$on("imageLoaded", function(){ 
   jQuery('img').height(80).width(80); 
}
于 2014-05-15T21:52:43.927 回答
1

我遇到了类似的问题,想在这里分享我的解决方案。

我有以下 HTML:

<div data-my-directive>
  <div id='sub' ng-include='includedFile.htm'></div>
</div>

问题:在父 div 指令的链接函数中,我想对子 div#sub 进行 jquery。但它只是给了我一个空对象,因为当指令的链接功能运行时 ng-include 还没有完成。所以首先我用 $timeout 做了一个肮脏的解决方法,它有效,但延迟参数取决于客户端速度(没有人喜欢这样)。

工作但很脏:

app.directive('myDirective', [function () {
    var directive = {};
    directive.link = function (scope, element, attrs) {
        $timeout(function() {
            //very dirty cause of client-depending varying delay time 
            $('#sub').css(/*whatever*/);
        }, 350);
    };
    return directive;
}]);

这是干净的解决方案:

app.directive('myDirective', [function () {
    var directive = {};
    directive.link = function (scope, element, attrs) {
        scope.$on('$includeContentLoaded', function() {
            //just happens in the moment when ng-included finished
            $('#sub').css(/*whatever*/);
        };
    };
    return directive;
}]);

也许它可以帮助某人。

于 2016-09-17T20:16:41.967 回答