1

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.

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.