0

I try to get a width from a $element in directive. but, it continues to return 0.

Can you tell me what is the problem? and, can you tell me the solution?

To see problem, i've created a demo :

  • directive

    angular.module('testApp').directive('testDirective', testDirective)
    function testDirective() {
        return {
            restrict: 'E',
            controller: 'TestController',
            controllerAs: 'vm',
            bindToController: true,
            scope: {}
        }
    }
    
  • controller

    angular.module('testApp').controller('TestController', TestController);
    
    TestController.$inject = ['$element'];
    
    function TestController($element) {
        var vm = this;
    
        init()
    
        function init(){
        vm.elWidth0 = $element.find("div")[0].clientWidth; 
        vm.elWidth1 = $element.find("div")[0].offsetWidth; 
        vm.elWidth2 = $element.prop('clientWidth'); 
        console.log(vm.elWidth0); //return 0
        console.log(vm.elWidth1); //return 0
        console.log(vm.elWidth2); //return 0
        }
    }
    
  • html

    <test-directive>
        <div>
            <button>a</button>
            <button>c</button>
            <button>d</button>
            <button>e</button>
            <button>f</button>
        </div>
    </test-directive>
    

Thank you for your advice

2
  • The most probable explanation is that the element has not actually rendered yet. You should probably use the link / link.post function to run your height detection code and even then, you may need to run it in a $timeout Commented Feb 2, 2016 at 2:13
  • hi @Phil. What should i do if necessary in a controller. and, Is the '$timeout' way a best practice? Commented Feb 2, 2016 at 7:58

1 Answer 1

2

Take a look at this plnkr: http://plnkr.co/edit/3D8kQUukMkXRld9kNYJ1?p=preview

It would appear that you're not getting a proper reference to the elements. Try using querySelector instead:

$element[0].querySelector('button').clientWidth;

UPDATE

The best place to put DOM manipulation in a directive is in the link function(which is actually post-link) because link happens after the directive html has been compiled.

The controller also is created after the directive html has been compiled but it's good to use the controller to separate logic that requires communication with an angular service. There's some really good information on directive link vs. controller here.

Your directive could then look something like this:

function testDirective() {
  return {
    restrict: 'E',
    controller: 'TestController',
    controllerAs: 'vm',
    bindToController: true,
    scope: {}, 
    link: function(scope, element, attrs) {
      scope.elWidth0 = element.find("div")[0].clientWidth; 
      scope.elWidth1 = element.find("div")[0].offsetWidth; 

      console.log(scope.elWidth0);
      console.log(scope.elWidth1);
    }
  }
}
Sign up to request clarification or add additional context in comments.

1 Comment

hi @paultrone. I'm so so sorry. I had created a wrong demo. So, i corrected a demo

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.