Stack Overflow is a community of 4.7 million programmers, just like you, helping each other.

Join them; it only takes a minute:

Sign up
Join the Stack Overflow community to:
  1. Ask programming questions
  2. Answer and help your peers
  3. Get recognized for your expertise

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

share|improve this question
    
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 – Phil 15 hours ago
    
hi @Phil. What should i do if necessary in a controller. and, Is the '$timeout' way a best practice? – sukyum 9 hours ago

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);
    }
  }
}
share|improve this answer
    
hi @paultrone. I'm so so sorry. I had created a wrong demo. So, i corrected a demo – sukyum 9 hours ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.