MikeDiam
MikeDiam

Reputation: 111

How can I bind to element height and wathch it on window resize or another event using Angular?

I have two elements .common and .userpanel 1. I need to give to the .userpanel height of common div on load 2. Keep binding on window resize event 3. Keep binding on another event (for example, I increase the height of common div, when I run function to expand child elements)

Upvotes: 5

Views: 1208

Answers (3)

Cosmin Ababei
Cosmin Ababei

Reputation: 7072

The trick is to create a watcher over the height of your desired element using $watch(). You can find its documentation here. Then you need to bind a function to the resize event on $window.

That's pretty much it. You can view an working example below. Notice how the element's height is exposed as a scope property.

angular
  .module('myApp', [])
  .directive('getHeight', function() {
    return {
      controller: ['$attrs', '$element', '$scope', '$window',
        function($attrs, $element, $scope, $window) {
          ///////////////
          // Variables //
          ///////////////

          // Used to create a debounced function
          var resizeTimeout;
          var scopeVariableName = $attrs.getHeight;

          ///////////////
          // Run block //
          ///////////////

          angular.element($window).bind('resize', onResize);
          $scope.$on('$destroy', function() {
            angular.element($window).unbind('resize', onResize);
          });

          $scope.$watch(getElementHeight, function(newValue) {
            $scope[scopeVariableName] = newValue;
          });

          ///////////////
          // Functions //
          ///////////////

          function getElementHeight() {
            return $element[0].clientHeight;
          }

          function onResize() {
            // setTimeout is used rather than $timeout as this doesn't trigger
            // a new digest cycle. we trigger a digest cycle only if needed.
            clearTimeout(resizeTimeout);
            resizeTimeout = setTimeout(function() {
              var elementHeight = getElementHeight();
              if ($scope[scopeVariableName] === elementHeight) {
                // The 2 values are identical. There's no need for a digest cycle
              } else {
                $scope.$evalAsync(function() {
                  $scope[scopeVariableName] = elementHeight;
                });
              }
            }, 50);
          }
        }
      ],
      scope: false,
      restrict: 'A'
    }
  });
html,
body {
  height: 100%;
  margin: 0;
}
body {
  padding: 50px;
}
.common-style {
  color: #ffffff;
  font-family: sans-serif;
  font-size: 30px;
  width: 30%;
}
#parent {
  background: blue;
  margin: 2.5% 0;
  height: 30%;
}
#child {
  background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.min.js"></script>

<div ng-app="myApp" style="height: 100%;">
  <label>Custom parent height:</label>
  <input type="number" ng-model="explicitParentHeight">
  <div>If nothing is written here, then the blue div will have a height of 30%</div>
  <div id="parent" class="common-style" get-height="parentHeight" ng-style="{height: explicitParentHeight + 'px'}">PARENT</div>
  <div id="child" class="common-style" ng-style="{height: parentHeight + 'px'}">CHILD - height: {{ parentHeight }}</div>
</div>

Upvotes: 0

Muthukannan Kanniappan
Muthukannan Kanniappan

Reputation: 2079

This directive can help bind height between elements, demo available at https://plnkr.co/edit/hpIlWxP2DbtGgVGdrcbk?p=preview

app.directive('bindTo', function($document, $window) {
  return {
    restrict: 'A',
    link: function(scope, element, attr) {

      if(!attr.bindTo) {
        console.log('bindTo element not defined');
        return;
      }

      var windowElm = angular.element($window), 
        bindToElm = angular.element($document[0].querySelector(attr.bindTo));

      if(!bindToElm) {
        console.log('defined bindTo element ', attr.bindTo, ' not found');
        return;
      }

      windowElm.on('resize', bindHeight);
      scope.on('someEvent', bindHeight);

      bindHeight();

      function bindHeight() {
        var bindToElmHt = bindToElm.height();
        element.css('height', bindToElmHt);
      }
    }
  }; 
});

Usage would be like,

<div class="common">
  Common
</div>
<div class="user-panel" bind-to=".common">
  User Panel
</div>

Upvotes: 3

ashfaq.p
ashfaq.p

Reputation: 5469

There are many javascript libraries to detect changes in element's dimensions.

One such is: detect-element-resize

You can use this to detect the change and then use the callback to reassign the height changes.

Upvotes: 0

Related Questions