Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ionic framework ionicView.entered event fired twice

I'm playing with this ionicView events that are fired whenever the views become active, and I'm using the side menu template that you can re-use when creating the project. It seems that if I put a listener for the $ionicView.entered event in the AppCtrl (the one used by the side menu template, which belongs to an abstract state in the ui-router configuration) it gets called twice in a row for any of the subviews (like, when using app.someotherview as a state).

I don't know if this is the expected behavior because from the documentation I would expect it to only fire once, no matter if I change the subview (the menuContent view).

I'd like to know if this is expected behavior and if so, how do I get to have an event fired only once every time it gets to show the side menu template.

This is what I've got written:

This is from the application module:

.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'); 

Then the AppCtrl is this:

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);
    });
}); 

The menu template:

<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">APPoint!</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>
like image 885
Adrián Pérez Avatar asked May 14 '15 11:05

Adrián Pérez


3 Answers

A simple workaround is:

$scope.$on('$ionicView.enter', function(ev) {
    if(ev.targetScope !== $scope)
        return;
    // Your code which should only run once
});
like image 197
Florian Avatar answered Nov 11 '22 09:11

Florian


The best option that I found to simulate onEnter event was to use in view controller :

$scope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState, fromParams) {
if (toState.name == "stateName")
    doSomething();

}
like image 42
icaro56 Avatar answered Nov 11 '22 09:11

icaro56


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.

like image 1
Rajush Avatar answered Nov 11 '22 08:11

Rajush