Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ng-view creating multiple controllers/scope

I am unaware of how to fix this current problem. I have 5 tabs on a page. Each tab loads a new page and controller via routing and ng-view. I have a $locationChangeStart on each tab to finish up some functionality before going to the next tab. However, if a user returns to the previous tab, then we get some issues. After finishing whatever it is they do with the tab and switch to another, the $locationChangeStart function will get fired numerous times, it seems that a new controller is being created every tab switch from the original tab.

so:

  • Current Tab = A
  • Switch to new tab (B)
  • $locationChangeStart fires as expected
  • Switch back to tab A
  • $locationChangeStart fires for Tab A again (wasn't expected as I'm not on that page anymore but okay)
  • Switch to new tab (C)
  • 2 $locationChangeStart fire. One with a new scope, other with original scope when first visited the tab.

This process will happen an infinite amount of times when switching to a from Tab A, the number calls going up by 1 each time.

plunker: working demo

index.html:

<div ng-controller="visitController">
  <h3>ng-view demo</h3>

  <ul class="nav nav-tabs">
    <li class="active">
      <a href="#/Information">Information</a>
    </li>
    <li><a href="#/Fingerprint">Fingerprint</a></li>
    <li><a href="#/Agenda">Agenda</a></li>
    <li><a href="#/Logistics">Logistics</a></li>
  </ul>

  <div ng-view>
  </div>
</div>

Tab 1:

<div ng-controller="InformationController">
    This is the information tab.
</div>

Tab 2:

<div>
    This is the Fingerprint tab.
</div>

main page js:

angular.module('app', []).config(['$routeProvider', '$locationProvider',
function ($routeProvider, $locationProvider) {
  $routeProvider.when('', {
      templateUrl: "Information.html",
      controller: visitController
  }).when('/Information', {
      templateUrl: "Information.html",
      controller: visitController
  }).when('/Fingerprint', {
      templateUrl: "Fingerprint.html",
      controller: visitController
  })

  $routeProvider
    .otherwise('/Information', {
      redirectTo: "Information.html"
    });
  }
]);

function visitController($scope, $http, $window, $route, $rootScope) {

}

Tab 1 JS

function InformationController($scope, $http, $window, $route, $rootScope) {
  $scope.activated = 0;
  $rootScope.$on('$locationChangeStart', function (event) {
      $scope.activated++;
      alert($scope.activated);
  });
}
like image 530
yaegerbomb Avatar asked May 03 '13 15:05

yaegerbomb


1 Answers

That's because you're attaching your event listener to $rootScope instead on $scope.

Each time InformationController is loaded you attach new $locationChangeStart event listener to the $rootScope.

When you switch between tabs, the $rootScope doesn't reload, it stays intact, so you just keep adding the same event listener each and every time. After switching to "Information" tab for the fifth time, you got yourself five listeners built up and listening.

Instead of $rootScope, use $scope, which will get $destroyed when route changes, and as such, will clear your previous listener.

like image 169
Stewie Avatar answered Sep 20 '22 22:09

Stewie