$ionicView.enter emited twice in a row. Expected behavior?


#1

Hi,
I’ve started a project using the sidemenu template and I’ve found that using the listeners for the view lifecycle http://ionicframework.com/docs/api/directive/ionView/ for the scope of the view that holds the sidemenu (this is the one in the menu.html template, which is shown when a sub state of app is active) the $ionicView.enter event listener is called twice in a row when the state becomes active.

I don’t know if that is expected behavior for the parent view when using nested views.

This is how I set the listeners, in the controller for that state.

angular.module('dashboard.controllers.app', [])
.controller('AppCtrl', function($scope, $ionicModal, $timeout, $ionicSideMenuDelegate, authService, $state) {
    $scope.logout = function() {
        authService.logout();
        $state.go('login');
    };

    $scope.$on('$ionicView.enter', function(){ //This is fired twice in a row
        console.log("App view (menu) entered.");
        console.log(arguments); 
    });

    $scope.$on('$ionicView.leave', function(){ //This just one when leaving, which happens when I logout
        console.log("App view (menu) leaved.");
        console.log(arguments);
    });
}); 

States are defined like this:

.config(function($stateProvider, $urlRouterProvider, $httpProvider) {
  $stateProvider

  .state('app', {
    url: "/app",
    abstract: true,
    templateUrl: "templates/menu.html",
    controller: 'AppCtrl'
  })

  .state('app.overview', {
    url: "/overview",
    views: {
      'menuContent': {
        templateUrl: "templates/overview.html",
        controller: 'OverviewCtrl'
      }
    }
  })

  .state('login', {
    url: "/login",
    templateUrl: "templates/identificationscreen.html",
    controller: "IdentificationCtrl"
  })

  .state('app.agenda', {
    url: "/agenda",
    views: {
      'menuContent': {
        templateUrl: "templates/agenda.html",
        controller: 'AgendaCtrl'
      }
    }
  });

  $httpProvider.interceptors.push('credentialsInjector');

  // if none of the above states are matched, use this as the fallback
  $urlRouterProvider.otherwise('/login'); 

And the code for the menu.html which I have slightly changed:

<ion-side-menus enable-menu-with-back-views="false">
  <ion-side-menu-content edge-drag-threshold="true">
    <ion-nav-bar class="bar-stable">
      <ion-nav-back-button>
      </ion-nav-back-button>
      <ion-nav-buttons side="left">
        <button class="button button-icon button-clear ion-navicon" menu-toggle="left">
        </button>
      </ion-nav-buttons>
    </ion-nav-bar>
    <ion-nav-view name="menuContent"></ion-nav-view>
  </ion-side-menu-content>

  <ion-side-menu side="left">
    <ion-header-bar class="bar-stable">
      <h1 class="title">Menu</h1>
    </ion-header-bar>
    <ion-content>
      <ion-list>
        <ion-item nav-clear menu-close href="#/app/overview">
          Overview
        </ion-item>
        <ion-item nav-clear menu-close href="#/app/agenda">
          Agenda
        </ion-item>
        <ion-item nav-clear menu-close ng-click="logout()">
          Logout
        </ion-item>
      </ion-list>
    </ion-content>
  </ion-side-menu>
</ion-side-menus>

From the docs I thought that no matter if its a parent view or not, if its still part of the current state, which it is because is the parent, the $ionicView.enter would only fire once. At least it was how I interpreted that situation. It also fires when changing the nested view, changing to a nested state like “app.overview” or “app.agenda”.

Anyway, the framework looks nice and it’s helping me a lot recently. Keep the good work!


#2

You can globally disable the caching mechanism used by ionic by doing:

$ionicConfigProvider.views.maxCache(0);

I haven’t tried that on my own though.

Else, the best way that worked for me was doing

$scope.$on("$ionicView.afterLeave", function () {
     $ionicHistory.clearCache();
}); 

This is to clear the cache before leaving the view to re-run controller every time you enter back again. I hope that does the trick for you. This will run the controller in a traditional way as the template gets loaded without having to listen for

$scope.$on('$ionicView.enter', function(event){ });

#3

It is the expected behavior because the parent view is also a “view”.

So all views in a state are notified for view entering.
But maybe you can use the event to decide if it is the right “View” entering.

$scope.$on('$ionicView.enter', function(event){ console.log(event); });

#4

@adyrhan Hii, did you figure this out ? I have the same issue. My $ionicView.enter is firing twice. I am using the sidemenu template. Can you please let me know if you figured it out ?

Noe of the solutions provided above worked.

Thanks.


#5

i am also facing the same issue.
my custom event gets fired twice.

please help.


#6

hi Ionic team,

please help.

thanks,