I'm trying to use an Angular JS directive to center the contents of a div.
This is the simplified version of the template:
<div id="mosaic" class="span12 clearfix" s-center-content>
<div ng-repeat="item in hits" id="{{item._id}}" >
</div>
</div>
This is the directive:
module.directive('sCenterContent', function() {
var refresh = function(element){
var aWidth= element.innerWidth();
var cWidth= element.children()[0].offsetWidth;
var cHeight= element.children()[0].offsetHeight;
var perRow= Math.floor(aWidth/cWidth);
var margin=(aWidth-perRow*cWidth)/2;
if(perRow==0){
perRow=1;
}
var top=0;
element.children().each(function(index, child){
$(child).css('margin-left','0px');
if((index % perRow)==0){
$(child).css('margin-left',margin+'px');
}
});
};
return {
link : function(scope, element, attrs) {
$(window).resize(function(event){
refresh(element);
});
}
};
});
It basically floats some inner divs and adds a margin to the first div in each row, so the content is centered.
This works fine when the browser is resized. The problem comes when I try to do a refresh just after initialization.
I have tried with the post linking function as seen in this question. The pre link and post link functions get called in the expected order but not after the children of the elemenet with the s-center-content directive get rendered. The call to refresh fails as no children are found.
How can I make a call to refresh ensureing the children have been processed?
I think using angular's $watch is a better, more elegant solution:
link : function(scope, element, attrs) {
$(window).resize(function(event){
refresh(element);
});
var watchCount = 0,
unWatcher = $watch(
function() {
return $('*[s-center-content] img').length !== 0;
},
function() {
// ensure refresh isn't called the first time (before the count of elements is > 0)
if (++watchCount === 1) {
return;
}
refresh(element);
// stop watching the element now that refresh has been called
unWatcher();
}, true);
}
About stop watching : AngularJS : Clear $watch
This is a recurring issue (Somewhere there's an issue associated with this, as well as a thread in the google forums..)
Angular has no way to know when the dom is finished, it can only know when the functions that it calls return (and any promises are resolved). If those functions are asynchronous and don't have a callback or a promise, there's no way to be notified.
The way I've seen it done (and the way I've done it) is with a setInterval that checks the DOM periodically to see if it's in a completed state. I hate this solution and will be grateful for an alternative, but, it does get the job done.
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