Reputation: 27394
I am fairly new to Angular and want to be able to bind to the height of an element. In my current case I want to bind the CSS bottom
on el1
to the height of el2
. They do not share 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 which looked promising but couldnt see how to extend it to allow me to specify which element I wanted to bind it to.
In a generic case, I guess what I am asking for is a directive to bind property X on Element 1 to property Y on Element 2.
Update
I have created a directive to do this but it isn't quite working yet. It fires correctly at the start but when I try to test it by manually updating the CSS of the el2
the watch doesnt fire
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);
}
});
}
};
});
Upvotes: 4
Views: 4561
Reputation: 1
I'm using a modified version of what you did. I added an offset attribute and a timeout for letting ui rendering 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);
});
}
};
});
Upvotes: 0
Reputation: 8758
You can easily do it with this simple directive. Basically it only watches for that attribute value to 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">
Upvotes: 0
Reputation: 27394
To anyone looking for the 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);
}
});
}
};
});
Upvotes: 3
Reputation: 4611
you can wrap you controllers in additional top level controller for example
<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 element in that controller
another way to create directive and apply on one of them, which will find the element from DOM and will apply the height on that
Upvotes: 0