Reputation: 1345
So I have an ng-repeat that loops over data objects and displays it in a list directive. One of the objects in the list should use the abbreviated version when the length of the text element is equal to or exceeds the length of the container. So what I have is this:
//this is the list directive
<shift-list selection="selection" shifts="shifts"></shift-list>
//this is the template of the list directive that adds site-base-name directive
<ion-item collection-repeat="shift in shifts">
<div class="item-text">
<site-base-name shift="shift"></site-base-name>
</div>
//and here is what my site-base-name directive looks like
return {
restrict: 'E',
link: function(scope, element) {
$timeout(function(){
scope.siteBaseWidth = element[0].offsetWidth;
scope.parentWidth = element.parent()[0].offsetWidth;
});
},
replace: true,
scope: {
shift: '='
},
template: ''+
'<div class="sitebase">{{(siteBaseWidth + 20 >= parentWidth) && shift.sites_abbreviation || shift.sites_name }} : {{shift.bases_name}}</div>'
}
}
So what I'm doing is nesting the directive site-base-name
inside the list directive and then finding the size of the element and its parent. Then I'm using the abbreviated version of the name (shift.sites_abbreviation
) if the size exceeds my condition (siteBaseWidth + 20 >= parentWidth
). The problem with this is the behavior I'm getting is buggy and inconsistent. It also applies the changes after the DOM is loaded, so you can see the text change within the window.
My question is what is the best way to find the width of the text element and parent element then apply a condition that decides what data to populate the binding with? Preferably a clean Angular solution.
Upvotes: 1
Views: 248
Reputation: 19193
Relying on the element offsetWidth
is not very clean, as if forces you to wait for the DOM to be updated (hence your $timeout
and the flickering observed).
A cheap way to solve your issue would be to initially display your text with an opacity of 0.01 (so it is not visible, but still takes some space), and with your site-base-name directive, once you know its size and adjust the text, you can set its opacity back to 1.
Now a better solution would be to get rid of this $timeout and offsetWidth. If you use a monospace font, you could just calculate thestring.length times pixelsPerCharacter, before even it is displayed.
Upvotes: 1