Angular directive snaps to element height
I am new to Angular and want to be able to bind to the height of an element. In my case, I want to bind the CSS bottom
to el1
the height el2
. They don't have a common controller. How can i do this?
<div id='el1' ng-controller='controller1' style='bottom: {{theHeightOfEl2}}'></div>
<div id='el2' ng-controller='controller2' style='height: 573px;'></div>
I found an answer on here that looked promising, but couldn't see how to expand it so that I could indicate which element I wanted to bind it to.
In general I am assuming that what I am asking is a directive to bind property X on item 1 to property Y on item 2.
Update
I created a directive for this, but it doesn't work yet. It fires correctly at the start, but when I try to test it by manually updating the CSS el2
, the clock doesn't start
m.directive('bindToHeight', function ($window) {
return {
restrict: 'A',
link: function (scope, elem, attrs) {
var attributes = scope.$eval(attrs['bindToHeight']);
var targetElem = angular.element(document.querySelector(attributes[1]));
// Watch for changes
scope.$watch(function () {
return targetElem.height();
},
function (newValue, oldValue) {
if (newValue != oldValue) {
// Do something ...
console.log('Setting bottom to ' + newValue);
elem.attr('bottom', newValue);
}
});
}
};
});
source to share
For anyone looking for an answer, here is what I used
Usage bind-to-height="[cssProperty, sourceElement]"
:
<div bind-to-height="['bottom','#addressBookQuickLinks']">
code:
m.directive('bindToHeight', function ($window) {
return {
restrict: 'A',
link: function (scope, elem, attrs) {
var attributes = scope.$eval(attrs['bindToHeight']);
var targetElem = angular.element(document.querySelector(attributes[1]));
// Watch for changes
scope.$watch(function () {
return targetElem.height();
},
function (newValue, oldValue) {
if (newValue != oldValue) {
elem.css(attributes[0], newValue);
}
});
}
};
});
source to share
you can wrap your controllers in an additional top-level controller like
<div ng-controller="PageController">
<div id='el1' ng-controller='controller1' style='bottom: {{theHeightOfEl2}}'></div>
<div id='el2' ng-controller='controller2' style='height: 573px;'></div>
</div>
and calculate and store the height of the element in that controller
another way is to create directive and apply on one of them which will find element from DOM and apply height on that
source to share
You can easily do it with this simple directive. Basically it only watches the value of this attribute change.
app.directive('bindHeight', function ($window) {
return {
link: function(scope, element, attrs){
scope.$watch(attrs.bindHeight, function(value) {
console.log(value);
element.css('height',value + 'px');
});
}
};
});
//$scope.myHeight
<div id="main-canvas" bind-height="myHeight">
source to share
I am using a modified version of what you did. I added an offset attribute and a timeout to allow ui render events to complete:
m.directive('bindToHeight', function ($window) {
return {
restrict: 'A',
link: function(scope, iElement, iAttrs) {
var attributes = scope.$eval(iAttrs.bindToHeight);
var targetElem = angular.element(document.querySelector(attributes[1]));
var offset = attributes[2]? parseInt(attributes[2]) : 0;
var timeoutId;
// Watch for changes
scope.$watch(function () {
timeoutId && $timeout.cancel(timeoutId);
timeoutId = $timeout(function () {
var total = targetElem.height() + offset;
//remove the px/em etc. from the end before comparing..
if (parseInt(iElement.css(attributes[0]).slice(0, -2)) !== total)
{
iElement.css(attributes[0], total);
}
}, 50, false);
});
}
};
});
source to share