Search code examples
angularjsangularjs-directiveangular-strapbatarang

How to proper cleanup child scopes of an Angular directive


Background: I am creating a directive based bgDropdown of angularstrap. My goal is to create a similar widget HTML select element, but with custom templates for each element.

The widget works fine. but using Batarang discovered that whenever the user displays the dropdown child scopes are created and are never destroyed. Thus, each time the dropdown is displayed more and more child scopes are created.

I need to understand how to do a proper cleaning of the children scopes.

Sample plunk: http://plnkr.co/edit/xP6HS9?p=preview

Step 1: Before first click.

Step 1: Pristine

Step 2: After first click and after to closed.

After first click

Step 3: After various opens and closes.

enter image description here


Solution

  • I believe this is actually an issue of $tooltip service as I'm able to see the same thing happens in the dropdown demo of AngularStrap itself.

    When showing the dropdown, the $tooltip.show() will clone the dropdown template and link with the same scope everytime, see tooltip.js#L198

    tipElement = $tooltip.$element = tipLinker(scope, function(clonedElement, scope) {});
    

    And in $tooltip.hide(), there is no code that destroy scopes created inside the template (e.g. by ng-repeat), thus the problem occur.

    The easiest workaround that I could imagine, is to specify a ng-controller to the rnDropdown.item.tpl.html template:

    <ul tabindex="-1" class="dropdown-menu" role="menu" rn-same-width ng-controller="rnDropdownItemCtrl">
    

    then listen to $destroy event in controller, to destroy its scope when the dropdown has been removed:

    .controller('rnDropdownItemCtrl', function ($scope, $element) {
      $element.on('$destroy', function () {
        $scope.$destroy();
      });
    })
    

    Example Plunker: http://plnkr.co/edit/j74pms?p=preview