Angular指令更新多个元素的高度以匹配最高的

Angular directive to update height of multiple elements to match the tallest

本文关键字:高度 Angular 更新 元素 指令      更新时间:2024-01-09

我对Angular的指令还很陌生,正在努力找出使用它们的正确方法。我正在使用ng repeat来填充元素列表。一旦中继器被加载,我想查看每个元素,找到哪一个是最高的(其中有最多的文本),然后强制所有元素达到这个大小。

在jQuery中实现这一点的方法如下:

var tallest = 0;
// Loop through each element
$('.element-class').each(function () {
    var thisHeight = $(this).height();      
    if (thisHeight > tallest)
        tallest = thisHeight;
});
// Apply height to all elements
$('.element-class').height(tallest);

有人能告诉我如何通过指令(或另一种更合适的Angular方式)来实现这一点吗。中继器看起来像这样。

<div class="element-class" ng-repeat="item in items">
    <div class="element-title" ng-bind="item.title"></div>
    <p class="element-text" ng-bind="item.description"></p>
</div>

以下是您可以做的。使用指令可以跟踪每个元素,并在最后一个元素上调用一个函数,该函数将计算每个元素的高度并找到最高的,然后将所有元素设置为该高度。您需要使用angular的$timeout,以确保在angular完成操纵dom之后才检查高度。这里有一些代码,下面我放置了一个指向plunker的链接。

HTML

<div equalize-height>
  <div class="element-class" equalize-height-add="item" ng-repeat="item in items">
    <div class="element-title" ng-bind="item.title"></div>
    <p class="element-text" ng-bind="item.description"></p>
  </div>
</div>

角度

.directive('equalizeHeight', ['$timeout', function($timeout){
return {
  restrict: 'A',
  controller: function($scope){
    console.log('equalizeHeightFor - controller');
    var elements = [];
    this.addElement = function(element){
      console.log('adding element:', element);
      elements.push(element);
      console.log(elements);
    }
    // resize elements once the last element is found
    this.resize = function(){
      $timeout(function(){
        console.log('finding the tallest ...');
        // find the tallest
        var tallest = 0, height;
        angular.forEach(elements, function(el){
          height = el[0].offsetHeight;
          console.log('height:', height);
          if(height > tallest)
            tallest = height;
          // console.log(el);
        });
        console.log('tallest:', tallest);
        console.log('resizing ...');
        // resize
        angular.forEach(elements, function(el){
          el[0].style.height = tallest + 'px';
        });
        console.log('-- finished --');
      }, 0);
    };
  }
};
}])
.directive('equalizeHeightAdd', [function($timeout){
return {
  restrict: 'A',
  require: '^^equalizeHeight',
  link: function(scope, element, attrs, ctrl_for){
    console.log('equalizeHeightAdd - link');
    // add element to list of elements
    ctrl_for.addElement(element);
    if(scope.$last)
      ctrl_for.resize();
  }
};
}])

这里有一个链接到一个plunker也看到它在行动:http://plnkr.co/edit/X4jmwZ?p=preview

您需要在ng repeat最后一个元素呈现在视图中之后运行代码。

角度方式的解决方案如下所示。

HTML

<div class="element-class" on-finish-ng-repeat-render ng-repeat="item in items">
    <div class="element-title" ng-bind="item.title"></div>
    <p class="element-text" ng-bind="item.description"></p>
</div>

指令

app.directive('onFinishNgRepeatRender', function($timeout) {
    return {
        restrict: 'A',
        link: function(scope, element, attr) {
            if (scope.$last === true) {
                $timeout(function() {
                    //this coade will execute right after ng-repeat rendering has been completed
                    var tallest = 0, currentElement = angular.element(element);
                    // Loop through each element
                    angular.forEach(angular.element(element), function(value, key) {
                        var thisHeight = angular.element(value).height();
                        if (thisHeight > tallest)
                            tallest = thisHeight;
                    });
                    // Apply height to all elements
                    currentElement.height(tallest);
                });
            }
        }
    }
});

希望这能帮到你,谢谢。

我也想这么做。这条线对我帮助很大。经过一番折腾,我找到了解决办法。

我想做的是获取所有元素的长度,并将所有元素的高度设置为最高。

因此,首先我需要通过指令检测ng repeat何时完成加载,在该指令中,一旦我检测到最后一个已经完成加载,我就必须找到所有元素的最高长度,并将其应用于所有元素。

HTML

<div class="col-lg-4" ng-repeat="category in categoriesList.categories" set-max-height> 
  <div class="catagory-item">
    <h1 class="text-center">{{category}}</h1>
  </div>
</div>

1) set-max-height是一个指令名称。2) category-item是类,通过使用这个类名,我想获得所有元素的高度,并将其设置为所有元素的最大高度。

指令

app.directive('setMaxHeight', ['$timeout',function($timeout) {
return {
    link: function ($scope, $element, $attrs) {
        //Belove code will run afer ng-repeat finished
        if ($scope.$last){
            //Get all element by class name
            var elements = document.getElementsByClassName("catagory-item");
            var maxHeight = 0;
            $timeout(function(){
                // Get the max height from all div
                for (var i = 0; i < elements.length; i++) {
                   var elementHeight = elements[i].offsetHeight;
                   if (elements[i].offsetHeight > maxHeight) {
                       maxHeight = elementHeight;
                   }
                }
                // set max height to the all div
                for (var i = 0; i < elements.length; i++) {
                    elements[i].style.height = maxHeight + "px"; 
                }   
            });
        }
    }
}
}]);

ragamufin的解决方案就像一个符咒(谢谢!)

但是,如果你计划在重复过程中过滤或添加新元素,你应该在"equalizeHeightAdd"指令的结尾放松"if"(否则它不会调整自己的大小),并在控制器上实现移除功能,如果元素被破坏,则移除它们:

    .directive('equalizeHeight', equalizeHeight)
    .directive('equalizeHeightAdd', equalizeHeightAdd);
    equalizeHeight.$inject = ['$timeout'];
    /* @ngInject */
    function equalizeHeight() {
        var directive = {
            bindToController: true,
            controller: ControllerName,
            controllerAs: 'vm',
            link: link,
            restrict: 'A',
            scope: {}
        };
        return directive;
        function link(scope, element, attrs) {
        }
    }
    ControllerName.$inject = ['$window', '$timeout'];
    /* @ngInject */
    function ControllerName($window, $timeout) {
        var elements = [];
        this.addElement = addElement;
        this.removeElement = removeElement;
        this.resize = resize;
        activate();
        function activate() {
            angular.element($window).on('resize', function () {
                angular.forEach(elements, function(el){
                    el[0].style.height = null;
                });
                resize();
            });
        }
        function addElement(element){
            elements.push(element);
            console.log(elements.length);
        }
        function removeElement(element){
            elements.splice(elements.indexOf(element),1);
        }
        // resize elements once the last element is found
        function resize(){
            $timeout(function(){
                // find the tallest
                var tallest = 0, height;
                angular.forEach(elements, function(el){
                    height = el[0].offsetHeight;
                    if(height > tallest)
                        tallest = height;
                });
                // resize
                angular.forEach(elements, function(el){
                    el[0].style.height = tallest + 'px';
                });
            }, 0);
        }
    }
    /* @ngInject */
    function equalizeHeightAdd(){
        return {
            restrict: 'A',
            require: '^^equalizeHeight',
            link: function(scope, element, attrs, ctrl_for){
                // add element to list of elements
                ctrl_for.addElement(element);
                ctrl_for.resize();
                element.on('$destroy', function () {
                    ctrl_for.removeElement(element);
                    ctrl_for.resize();
                });
            }
        };
    }

很抱歉,由于缺乏声誉,我无法对他的回答发表评论,但我认为这是一个非常重要的补充。也很抱歉格式不同,但这就是我在项目中使用它的方式,但基本上是一样的。