Access child elements of a custom directive without jQuery

Problem

I've written a custom directive for a dropdown menu. The elements are absolutely positioned within a relatively positioned parent, so I need to get the height of the dropdown trigger element in order to move the actual menu below it. The trigger is a child of the directive element. I want to avoid using full-blown jQuery and instead use Angular's jqLite.

My attempt so far consists of a function added to the scope inside the directive's link function (so as to have access to element), but I'm not able to chain either find() or children() off that to find the child element.

My link and controller:

link: function(scope, element, attrs) {
    scope.clicked = false;
    scope.positionDropdown = function() {
        if (!scope.clicked) {
            scope.clicked = true;
            scope.buttonHeight = element[0].find('button').offsetHeight;
        }
    }
},
controller: function($scope) {
    'use strict';
    $scope.menuActive = false;
    $scope.toggleMenu = function () {
        $scope.positionDropdown();
        $scope.menuActive = !$scope.menuActive;
    };
}

What this should do is, when the button is first clicked, the scope variable buttonHeight should be defined with the element's height. Instead, I get an error in Chrome Dev Tools:

TypeError: undefined is not a function
    at Scope.scope.positionDropdown (http://localhost:3000/directives/dropdown/dropdown-directive.js:17:57)
    at Scope.$scope.toggleMenu (http://localhost:3000/directives/dropdown/dropdown-directive.js:25:28)
    at Parser.functionCall (http://localhost:3000/angular/angular.js:10656:21)
    at http://localhost:3000/angular/angular.js:18838:17
    at Scope.$get.Scope.$eval (http://localhost:3000/angular/angular.js:12518:28)
    at Scope.$get.Scope.$apply (http://localhost:3000/angular/angular.js:12616:23)
    at HTMLButtonElement.<anonymous> (http://localhost:3000/angular/angular.js:18837:21)
    at http://localhost:3000/angular/angular.js:2810:10
    at Array.forEach (native)
    at forEach (http://localhost:3000/angular/angular.js:320:11)

Here's my template:

<div class="dropdown" ng-class="{active: menuActive}">
<button ng-click="toggleMenu()">{{ngLabel}}<i ng-class="ngIcon" ng-if="ngIcon"></i></button>
<ul ng-show="menuActive" ng-style="{top: buttonHeight}"ng-transclude>
</ul>

I've set up a breakpoint to play around with this. element[0] works, but the find() method off that gives me TypeError: undefined is not a function. element[0].children(document.querySelector('button')) also errors with the same result. Why don't these methods of selecting the dropdown menu work? How can I select this without resorting to jQuery and without limiting myself to a single dropdown on the page?

Problem courtesy of: raddevon

Solution

I didn't get your question but if you want to select child of an element in Angular, you could do this:

    link:function(scope,elem,attr){

            // to select parent of parent of current element : 
            elem.parent().parent();
             // to select parent of current element : 
            elem.parent();
             // to select Child(a) of current element : 
            elem.children('a');
            // to select all Childs of current element : 
            elem.children();
            // getting element height
            elem.height();
            // window height : 
             $(window).height();
             // document height:
             $(document).height();
             // distance of your elem to top of the page : 
             $(window).scrollTop() + $(window).height();




    }
Solution courtesy of: Milad

Discussion

Try setting an Id on the button in question, eg <button id="myTrigger"></button>, and then use:

angular.element($document.getElementById('#myTrigger'));

Alternatively, loop through the children using elem.children(), and look for a button type.

Discussion courtesy of: Matt Way

This recipe can be found in it's original form on Stack Over Flow.