Reputation: 111
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
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
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
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