Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular JS viewContentLoaded loading twice on initial homepage load

I noticed that on my initial homepage load, my viewContentLoaded is firing twice, why is that ?

app.run(function 
    ($rootScope,$log) {
      'use strict';
      $rootScope.$state = $state;
      $log.warn("gets here");

      $rootScope.$on('$viewContentLoaded',function(){
        $log.warn("gets here2");
      });
    });

Output on page load

"gets here" 
"gets here2" 
"gets here2"

And my routing as follows

$urlRouterProvider.when('', '/');

  // For any unmatched url, send to 404
  $urlRouterProvider.otherwise('/404');

  $stateProvider
    .state('home', {
      url: '/',
      templateUrl: 'views/search.html',
      controller: 'SearchCtrl'
    })

My Index.html

  <div id="canvas">
    <ng-include src="'views/partials/header.html'"></ng-include>
    <!-- container -->
    <div ui-view ></div>
    <!-- /container -->
    <ng-include src="'views/partials/footer.html'"></ng-include>
  </div>
like image 450
StevieB Avatar asked Jun 23 '15 10:06

StevieB


2 Answers

It is just specifics of uiView directive implementation. It fires the $viewContentLoaded event during initialization (link) phase. At this point no state is yet known, but the event is still fired.

And then after the event is fired again once the $state service actually resolves your home state, makes transition into it, loads templates etc.

So to sum up, it happens not because of bad configuration nor your templates are loaded twice. It's just how uiView works.

You can even verify it by completely commenting out your state definitions and most of your index.html contents (except for ui-view itself). The $viewContentLoaded will still be fired once.

Source code excerpts:

uiView directive declaration:

{
    restrict: 'ECA',
    terminal: true,
    priority: 400,
    transclude: 'element',
    compile: function (tElement, tAttrs, $transclude) {
      return function (scope, $element, attrs) {
        ...
        updateView(true);
        ...
      }
    }
 }

and the updateView function

    function updateView(firstTime) {
      ...
      currentScope.$emit('$viewContentLoaded');
      currentScope.$eval(onloadExp);
    }

For more information see complete source code on GitHub - viewDirective.js

like image 50
FunkyOne Avatar answered Sep 16 '22 15:09

FunkyOne


Why it is getting call twice?

I'm sure that your serach.html page has again contain a ui-view, that is calling trying to load a view and at the end $emiting the $viewContentLoaded event. Simply As many number of ui-view rendered on the html that will surely $emit the $viewContentLoaded event.


As you want to make sure your event should be get call only once then you should put event on $stateChangeSuccess which will ensure that it will get fired only once after all the ui-views gets loaded via state.

Code

$rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams){ 
   ///...code here 
});
like image 32
Pankaj Parkar Avatar answered Sep 17 '22 15:09

Pankaj Parkar