App structure and routing

Hi all,

I’m developing my first application with Ionic (wonderful framework!) and I have a few questions about how to structure my pages and use the router…

The main pages of my application are a login page and a page with three tabs that the user can only view when connected. They are wrapped in nav-page directives and powered by a Nav Router controller. So here are my questions:

  1. How to redirect the user to the login page if no authentication
    token has been stored locally? In other words: how to redirect the
    user from one route to another from a controller?
  2. In this case, is it possible not to use the animation set on the Nav
    Router (animation=“slide-left-right-ios7”)?
  3. I’d like to hide the navigation bar on the login page, is it
    possible?
  4. It is written in the documentation that “the Nav Router can also be
    updated from child view controllers such as tabs” but I can’t find
    how? I’d like to define a route for each tab so that accessing one
    of these routes automatically activates the corresponding tab.

Many thanks in advance! Best regards,

David

1 Like

Hi davidgeilfus,
i’m also an absolute newbie to ionic and angular, but maybe i can help with topic 1:

  1. This is done via the $location (Provider(?)). reference it in your controller like:

.controller(‘SearchCtrl’, function($scope, $rootScope, $routeParams, $location, …

Then you can redirect the user via:

if(!loggedin){
  $location.path("/");
}
1 Like

Hey @davidgeilfus, welcome to Ionic :smile:

For #1, what I recommend is a service that manages login states, something like this:

angular.module('myapp', [])

.factory('User', function($rootScope, $location) {
  var isLoggedIn = false;

  // Load auth token from somewhere, like localStorage
  isLoggedIn = window.localStorage['token'] != nulll 


  $rootScope.$on('user.logout', function() {
    isLoggedIn = false;

    // redir to login page
    $location.path('/');
  });

  return {
    isLoggedIn: function() { return isLoggedIn; }
    login: function(username, password) {
      // Do login here
      // If login worked, trigger event
      $rootScope.$broadcast('user.login');
    },
    logout: function() {
      $rootScope.$broadcast('user.logout');
    }
  }
});

You can also listen for those events in your other controllers and such.

  1. In terms of not using the animation in this case, right now the answer is no without manually removing the classname from the nav-router div, but we are overhauling the nav stuff so that should work in the future.

  2. To hide the nav bar on just that page, use <nav-page hide-nav-bar="true"></nav-page>

  3. In terms of activating that specific tab, that’s a little more tricky and we are working to make this more clear. For now, perhaps this topic will help: Switch tab in controller

5 Likes

@ageibert and @max: thank you very much for your answers! It helps a lot!

Best regards,

David

@max how would you recommend to setup a filter which intercepts all page movements and checks if there’s a user logged in? It sounds simple but it’s proving a bit tricky. The problem seems to revolve around the $location.path call. I have this run config:

.run(function ($rootScope, $state, $location, AuthenticationService) {
$rootScope.$on("$stateChangeStart", function(event, curr, prev){
console.log('checking the validity of the route: ’ + curr.requireSession + ’ ’ + !AuthenticationService.is_logged_in());
if ( curr.requireSession && !AuthenticationService.is_logged_in() ){
$location.path("/login");
}
});
})

This sometimes works and sometimes doesn’t work. I’ve noticed that when this in the console:

Uncaught TypeError: Cannot call method ‘insertBefore’ of null

When it doesn’t work, I notice that even though the browser URL window shows the /login path, the page still stays on the protected page I was trying to reach while not authenticated. Further, the order of execution in the browser console shows that the login page is attempted first before the protected page is attempted.

Here is a simplified version of what I’m using :

.run(function ($http, $rootScope, $location, $state, AccountService) {

    $rootScope.$on('$stateChangeStart', function (event, next, current) {

        if(next.name.indexOf('main') !== -1 ) {

            var hasToken = AccountService.hasToken();

            if(!hasToken) {
                event.preventDefault();
                $state.go('entry');
            }
        }

    });
})

Consider adding the event.preventDefault(); to your code. Without, I found the navigation would continue to the original requested state as well.

3 Likes

@Calendee thanks man. That seems to have stabilised things. And on we go.