AngularJs event to call after content is loaded

AngularjsEventsLoaded

Angularjs Problem Overview


I have a function which I want to call after page content is loaded. I read about $viewContentLoaded and it doesn't work for me. I am looking for something like

document.addEventListener('DOMContentLoaded', function () { 
     //Content goes here 
}, false);

Above call doesn't work for me in AngularJs controller.

Angularjs Solutions


Solution 1 - Angularjs

According to documentation of $viewContentLoaded, it supposed to work

> Emitted every time the ngView content is reloaded.

$viewContentLoaded event is emitted that means to receive this event you need a parent controller like

<div ng-controller="MainCtrl">
  <div ng-view></div>
</div>

From MainCtrl you can listen the event

  $scope.$on('$viewContentLoaded', function(){
    //Here your view content is fully loaded !!
  });

Check the Demo

Solution 2 - Angularjs

Angular < 1.6.X

angular.element(document).ready(function () {
    console.log('page loading completed');
});

Angular >= 1.6.X

angular.element(function () {
    console.log('page loading completed');
});

Solution 3 - Angularjs

fixed - 2015.06.09

Use a directive and the angular element ready method like so:

js
.directive( 'elemReady', function( $parse ) {
   return {
       restrict: 'A',
       link: function( $scope, elem, attrs ) {    
          elem.ready(function(){
            $scope.$apply(function(){
                var func = $parse(attrs.elemReady);
                func($scope);
            })
          })
       }
    }
})
html
<div elem-ready="someMethod()"></div>

or for those using controller-as syntax...

<div elem-ready="vm.someMethod()"></div>

The benefit of this is that you can be as broad or granular w/ your UI as you like and you are removing DOM logic from your controllers. I would argue this is the recommended Angular way.

You may need to prioritize this directive in case you have other directives operating on the same node.

Solution 4 - Angularjs

You can directly call it by adding {{YourFunction()}} after HTML element.

Here is a Plunker Link.

Solution 5 - Angularjs

I had to implement this logic while handling with google charts. what i did was that at the end of my html inside controller definition i added.

  <body>
         -- some html here -- 
--and at the end or where ever you want --
          <div ng-init="FunCall()"></div>
    </body>

and in that function simply call your logic.

$scope.FunCall = function () {
        alert("Called");
}

Solution 6 - Angularjs

var myM = angular.module('data-module');

myM.directive('myDirect',['$document', function( $document ){
    
    function link( scope , element , attrs ){
        
        element.ready( function(){
            
        } );
        
        scope.$on( '$viewContentLoaded' , function(){
            
            console.log(" ===> Called on View Load ") ;
            
        } );
         
    }
    
    return {
        link: link
    };
    
}] );

Above method worked for me

Solution 7 - Angularjs

you can call javascript version of onload event in angular js. this ng-load event can be applied to any dom element like div, span, body, iframe, img etc. following is the link to add ng-load in your existing project.

download ng-load for angular js

Following is example for iframe, once it is loaded testCallbackFunction will be called in controller

EXAMPLE

JS

	// include the `ngLoad` module
	var app = angular.module('myApp', ['ngLoad']);
	app.controller('myCtrl', function($scope) {
		$scope.testCallbackFunction = function() {
		  //TODO : Things to do once Element is loaded
		};

	});  
 

HTML

  <div ng-app='myApp' ng-controller='myCtrl'> 
      <iframe src="test.html" ng-load callback="testCallbackFunction()">  
  </div>

Solution 8 - Angularjs

If you're getting a $digest already in progress error, this might help:

return {
        restrict: 'A',
        link: function( $scope, elem, attrs ) {
            elem.ready(function(){

                if(!$scope.$$phase) {
                    $scope.$apply(function(){
                        var func = $parse(attrs.elemReady);
                        func($scope);
                    })
                }
                else {

                    var func = $parse(attrs.elemReady);
                    func($scope);
                }

            })
        }
    }

Solution 9 - Angularjs

I was using {{myFunction()}} in the template but then found another way here using $timeout inside the controller. Thought I'd share it, works great for me.

angular.module('myApp').controller('myCtrl', ['$timeout',
function($timeout) {
var self = this;

self.controllerFunction = function () { alert('controller function');}

$timeout(function () {
	var vanillaFunction = function () { alert('vanilla function'); }();
	self.controllerFunction();
});

}]);

Solution 10 - Angularjs

Running after the page load should partially be satisfied by setting an event listener to the window load event

window.addEventListener("load",function()...)

Inside the module.run(function()...) of angular you will have all access to the module structure and dependencies.

You can broadcast and emit events for communications bridges.

For example:

  • module set onload event and build logic
  • module broadcast event to controllers when logic required it
  • controllers will listen and execute their own logic based on module onload processes.

Solution 11 - Angularjs

If you want certain element to completely loaded, Use ng-init on that element .

e.g. <div class="modal fade" id="modalFacultyInfo" role="dialog" ng-init="initModalFacultyInfo()"> ..</div>

the initModalFacultyInfo() function should exist in the controller.

Solution 12 - Angularjs

I found that if you have nested views - $viewContentLoaded gets triggered for every of the nested views. I've created this workaround to find the final $viewContentLoaded. Seems to work alright for setting $window.prerenderReady as required by Prerender (goes into .run() in the main app.js):

// Trigger $window.prerenderReady once page is stable
// Note that since we have nested views - $viewContentLoaded is fired multiple
// times and we need to go around this problem
var viewContentLoads = 0;
var checkReady = function(previousContentLoads) {
  var currentContentLoads = Number(viewContentLoads) + 0; // Create a local copy of the number of loads
  if (previousContentLoads === currentContentLoads) { // Check if we are in a steady state
    $window.prerenderReady = true; // Raise the flag saying we are ready
  } else {
    if ($window.prerenderReady || currentContentLoads > 20) return; // Runaway check
    $timeout(function() {checkReady(currentContentLoads);}, 100); // Wait 100ms and recheck
  }
};
$rootScope.$on('$stateChangeSuccess', function() {
  checkReady(-1); // Changed the state - ready to listen for end of render
});
$rootScope.$on('$viewContentLoaded', function() {
  viewContentLoads ++;
});

Solution 13 - Angularjs

var myTestApp = angular.module("myTestApp", []); 
myTestApp.controller("myTestController", function($scope, $window) {
$window.onload = function() {
 alert("is called on page load.");
};
});

Solution 14 - Angularjs

The solution that work for me is the following

app.directive('onFinishRender', ['$timeout', '$parse', function ($timeout, $parse) {
    return {
        restrict: 'A',
        link: function (scope, element, attr) {
            if (scope.$last === true) {
                $timeout(function () {
                    scope.$emit('ngRepeatFinished');
                    if (!!attr.onFinishRender) {
                        $parse(attr.onFinishRender)(scope);
                    }
                });
            }

            if (!!attr.onStartRender) {
                if (scope.$first === true) {
                    $timeout(function () {
                        scope.$emit('ngRepeatStarted');
                        if (!!attr.onStartRender) {
                            $parse(attr.onStartRender)(scope);
                        }
                    });
                }
            }
        }
    }
}]);

Controller code is the following

$scope.crearTooltip = function () {
     $('[data-toggle="popover"]').popover();
}

Html code is the following

<tr ng-repeat="item in $data" on-finish-render="crearTooltip()">

Solution 15 - Angularjs

I use setInterval to wait for the content loaded. I hope this can help you to solve that problem.

var $audio = $('#audio');
var src = $audio.attr('src');
var a;
a = window.setInterval(function(){
    src = $audio.attr('src');
    if(src != undefined){
        window.clearInterval(a);
        $('audio').mediaelementplayer({
            audioWidth: '100%'
        });
    }
}, 0);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser3233772View Question on Stackoverflow
Solution 1 - AngularjsTasnim RezaView Answer on Stackoverflow
Solution 2 - AngularjshariszamanView Answer on Stackoverflow
Solution 3 - AngularjsjusopiView Answer on Stackoverflow
Solution 4 - AngularjsblueView Answer on Stackoverflow
Solution 5 - AngularjsSaad ZulfiqarView Answer on Stackoverflow
Solution 6 - AngularjsAlok DView Answer on Stackoverflow
Solution 7 - AngularjsDarshan JainView Answer on Stackoverflow
Solution 8 - AngularjsJohn SmithView Answer on Stackoverflow
Solution 9 - AngularjsNhanView Answer on Stackoverflow
Solution 10 - AngularjsLuis D. Vazquez RiveraView Answer on Stackoverflow
Solution 11 - AngularjsNetDeveloperView Answer on Stackoverflow
Solution 12 - AngularjsMaksymView Answer on Stackoverflow
Solution 13 - AngularjsShreyansh KumarView Answer on Stackoverflow
Solution 14 - AngularjsJorge Santos NeillView Answer on Stackoverflow
Solution 15 - AngularjsxiangryView Answer on Stackoverflow