a7omiton
a7omiton

Reputation: 1617

Listen for directive to have completed loading in DOM - AngularJS

I would like to provide a loading indication as long as the directive has not finished loading all it's child elements on the page.

This portion of my app has tabs which when clicked will load the tab content. The problem I have is that some tabs content takes a long time to render.

I assumed it was my HTTP request which was causing a delay in the rendering and resorted to using custom promises, but after implementing that I found it was actually the DOM rendering of the directive that was taking so long.

What would be the correct event to listen to in the directive if I want to display a loading indicator before all the content is rendered within this directive? As far as I know, $viewContentLoaded is only used for the ngView directive, but this directive is a sub-directive of ngView so it does not apply (i think).

The code is pretty basic:

Controller:

angular.module('app', [])

.controller('MyController', ['$scope', 'Service', function($scope, Service) {
    
    $scope.get_data = function(user) {
        Service.getsomething(user).then(function(response) {
            $scope.data = response.data;
        },
        function(error) {
            console.log(error);
        });
    };
    
}])
.directive('tab', function() {
        return {
            restrict: 'E',
            templateUrl: 'templates/tab.html'
        };
    })

HTML:

<div role="tabpanel">
    <ul class="nav nav-pills col-lg-9 col-lg-offset-3" role="tablist">
        <li toggle-tabs class="active">
             <a href="#apanel">Panel</a>
        </li>
    </ul>

    <div class="tab-content col-lg-12">

        <tab></tab> //within here there are many forms

    </div>
</div>

Upvotes: 3

Views: 1333

Answers (1)

Estus Flask
Estus Flask

Reputation: 222319

angular.module('app').directive('tab', function($timeout, $rootScope) {
  return {
      restrict: 'E',
      templateUrl: 'templates/tab.html',
      link: function (scope, element, attrs, ctrl) {
        $timeout(function () {
          $rootScope.$emit('directive-dom-is-most-likely-there');
        });
      }
  };
});

You can't be sure that DOM is there when link runs, it depends on the implementation of nested directives (e.g. ng-repeat is known to be a late bloomer). Either you can't be sure that none of them has async stuff that needs some time to be completed, but $timeout with zero delay is ok for cosmetic things.

It depends on the context, it is not necessary to pollute $rootScope when you can talk to parent directive with require.

Keep in mind that it is more straightforward to make the directive self-contained with its own loading indicator instead of the global one.

Upvotes: 2

Related Questions