I'm having the old variable height navigation problem: A position: fixes
navigation on top and a content with margin-top: $naviHeight
below.
The navigation can change height when data is loaded asynchronously and so the content's margin has to change with it.
I want this to be self contained. So no code where the data is loaded but only in the involved html-elements/directives.
Currently I'm doing it in AngularJS 1.2.0 with a timer like this:
/*
* Get notified when height changes and change margin-top
*/
.directive( 'emHeightTarget', function(){
return {
link: function( scope, elem, attrs ){
scope.$on( 'heightchange', function( ev, newHeight ){
elem.attr( 'style', 'margin-top: ' + (58+newHeight) + 'px' );
} );
}
}
})
/*
* Checks this element periodically for height changes
*/
.directive( 'emHeightSource', ['$timeout', function( $timeout ) {
return {
link: function( scope, elem, attrs ){
function __check(){
var h = elem.height();
if( h != scope.__height ){
scope.__height = h;
scope.$emit( 'heightchange', h );
}
$timeout( __check, 1000 );
}
__check();
}
}
} ] )
This has the obvious drawback of using the timer (which i feel kind of ugly) and a certain delay after the navigation resized until the content is moved.
Is there a better way to do this?
This works by registering a watcher in emHeightSource
which is called every $digest
. It updates the __height
property which is in turn watched in emHeightTarget
:
/*
* Get notified when height changes and change margin-top
*/
.directive( 'emHeightTarget', function() {
return {
link: function( scope, elem, attrs ) {
scope.$watch( '__height', function( newHeight, oldHeight ) {
elem.attr( 'style', 'margin-top: ' + (58 + newHeight) + 'px' );
} );
}
}
} )
/*
* Checks every $digest for height changes
*/
.directive( 'emHeightSource', function() {
return {
link: function( scope, elem, attrs ) {
scope.$watch( function() {
scope.__height = elem.height();
} );
}
}
} )
You can monitor height change of your element without using Div, just writing a $watch
statement:
// Observe the element's height.
scope.$watch
(
function () {
return linkElement.height();
},
function (newValue, oldValue) {
if (newValue != oldValue) {
// Do something ...
console.log(newValue);
}
}
);
May be you should watch for $window
' dimensions changes , something like:
.directive( 'emHeightSource', [ '$window', function( $window ) {
return {
link: function( scope, elem, attrs ){
var win = angular.element($window);
win.bind("resize",function(e){
console.log(" Window resized! ");
// Your relevant code here...
})
}
}
} ] )
I used a combination of $watch and resize event. I found without scope.$apply(); in resize event, the height changes on the element is not always picked up by $watch.
link:function (scope, elem) {
var win = angular.element($window);
scope.$watch(function () {
return elem[0].offsetHeight;
},
function (newValue, oldValue) {
if (newValue !== oldValue)
{
// do some thing
}
});
win.bind('resize', function () {
scope.$apply();
});
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With