user3427320
user3427320

Reputation: 11

Calculate width of element - Angular Directive

I am new to angular. I am using angular1.4 and bootstrap. Problem: I have a span whose width grows or shrinks depending on the text content which is bound.

<div myStyleDir>
   <span>{{someContent}}</span>
</div>

In the scope:

$scope.someContent = "abcdefgh";

Based on the width of this span in the DOM, I have to proceed with some other calculations which I want to do using a directive myStyleDir. In the link function of directive, the jQuery-lite 'element' param width is coming as '0'.

Span is not yet rendered when the 'link' function is getting executed ? How do I get the width of the <span>{{someContent}}</span>element inside my link function ? If this is not a feasible approach please suggest an alternative. Thanks in advance !

Upvotes: 0

Views: 2815

Answers (2)

ryanlutgen
ryanlutgen

Reputation: 3051

I am assuming you are using Angular 1.x, so this should work for you:

HTML:

<my-style-directive>{{test}}</my-style-directive>

Directive JS:

.directive("myStyleDirective", ['$timeout', function($timeout) {
  return {
    restrict: 'E',
    scope: true,
    link: function(scope, elem, attrs) {
      var getWidth = function() {
        $timeout(function() {
          console.log(elem[0].getBoundingClientRect().width);
        });
      };

      getWidth();

      scope.$watch('test', function (newval, oldval) {
        if (newval !== oldval) {
          getWidth();
        }
      });
    }
  };
}]);

Plnkr to show: http://plnkr.co/edit/eVxDZTmjY22yG1aOScwC

Essentially what this is doing is putting a wrapper around whatever content you want to get the width of. Putting it as an attribute on a div means the width will read as however wide the parent is, e.g. you have a div on the top most level, the width of the div will be the width of the body. Without this approach, the only method of getting the width would be to do some wonky calculation and it would be coupled to your CSS.

The $timeout is to ensure the DOM is finished rendering to get an accurate reading. Essentially what $timeout does is execute when the JS event loop is empty, i.e. after everything has initialized and everything rendered. To see more about how timeouts work in JS, see here: https://www.youtube.com/watch?v=8aGhZQkoFbQ#t=10m44s

Upvotes: 2

Prasad Shinde
Prasad Shinde

Reputation: 664

You can use directive like this:

.directive('YourDirectiveName', function() {
    return {
        restrict: 'EA',
        scope: {data:'='},
        link: function(scope, iElement, iAttrs) {
           var elementRect = iElement[0].getBoundingClientRect();
             var width = elementRect.width;
             var height = elementRect.height;
             .......
        }
    }
});

Note: While developing anything using angular directive you should log content wherever you want. So that it will help you alot in your development.

I have used this while developing graphs(SVG) using angular for my web apps and mobile apps.

Upvotes: 0

Related Questions