Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Aurelia - Switching between app roots with different route configurations

Tags:

aurelia

UPDATE

Could this issue have something to do with mu problem? https://github.com/aurelia/framework/issues/400


I have an Aurelia application with two different roots, one for loggen in users, and another for anonymous users.

I have in other Aurelia apps implemented a chanaging of app root based on the approach in this answer. This works very well when the login module is an "isolated" module with no additional routes, but I'm having a hard time getting it to work now.

index.js - root for anonymous users

import {inject, useView, Aurelia} from "aurelia-framework";
import AuthService from "./services/auth-service";

@useView("app.html")
@inject(AuthService)
export class Index {   
    constructor(authService) {
        this.auth = authService;
    }

    configureRouter(config, router) {
        config.title = "Super Secret Project";
        config.options.pushState = true;
        config.map([
            { route: ["","home"], moduleId: "home", nav: true, title: "Beginscherm" },
            { route: "over", moduleId: "about", nav: true, title: "Over" },
            { route: "inloggen", moduleId: "account/login", nav: false, title: "Inloggen" }
        ]);

        this.router = router;        
    }
}

ic-app.js - root for logged in users

import {useView, inject} from "aurelia-framework";
import {RequestStatusService} from "./services/request-status-service";
import AuthService from "./services/auth-service";

@useView("app.html")
@inject(RequestStatusService, AuthService)
export class App {
    constructor(requestStatusService, authService) {
        this.requestStatusService = requestStatusService;
        this.auth = authService; // we use it to bind it to the nav-bar-top
    }

    configureRouter(config, router) {
        config.title = "Super Secret Project";
        config.options.pushState = true;
        config.map([
            { route: ["", "selecteer-school"], moduleId: "ic/select-school", nav: false, title: "Selecteer School" },
            { route: "dashboard", moduleId: "ic/dashboard", nav: true, title: "Beginscherm" },
        ]);

        this.router = router;
    }
}

login code on auth-service.js

logIn(userData, rememberMe = false) {
    this.requestStatusService.isRequesting = true;
    return this.http
        .fetch("/token", { method: "POST", body: userData })
        .then((response) => response.json())
        .then(response => {
            if (response.access_token) {
                this.setAccessToken(response.access_token, response.userName, rememberMe);
                this.app.setRoot("ic-app");
            }
        });
}

and...

log off code in auth-service.js

logOff() {
    AuthService.clearAccessToken();
    this.app.setRoot("index");
}

The Problem

Setting the different app roots works as expected, the problem is that I would expect the new app root to automatically navigate to the default route of the new root, bit it tries to load the route it was on the moment setRoot(...) is called.

To illustrate with an example,

  1. I'm on the login page. current route: /inloggen
  2. I click the log in button. app.setRoot("ic-app") is called
  3. New root is loaded; configureRouter in ic-app.js is called, and then...
  4. Console error: Route not found: /inloggen

The new root tries to stay in the same /inloggen route, but I would like it to load, or navigate to, the default route for that app root. The same happens on logging out.

How can I force the app to navigate to the default route after changing root?

like image 638
Sergi Papaseit Avatar asked Jun 30 '16 10:06

Sergi Papaseit


2 Answers

I got this working great, I answered more about how to in this stackoverflow thread:

Aurelia clear route history when switching to other app using setRoot

Basically do the following

this.router.navigate('/', { replace: true, trigger: false });
this.router.reset();
this.router.deactivate();

this.aurelia.setRoot('app');
like image 187
Johan O Avatar answered Nov 18 '22 21:11

Johan O


In the router for anonymous users use the mapUnknownRoutes. Like this:

configureRouter(config, router) {
    config.title = "Super Secret Project";
    config.options.pushState = true;
    config.map([
        { route: ["","home"], moduleId: "home", nav: true, title: "Beginscherm" },
        { route: "over", moduleId: "about", nav: true, title: "Over" },
        { route: "inloggen", moduleId: "account/login", nav: false, title: "Inloggen" }
    ]);

     config.mapUnknownRoutes(instruction => {
       //check instruction.fragment
       //return moduleId
       return 'account/login'; //or home
     });

    this.router = router;        
}

Do the same strategy in the other router. Now, try to logout and login again, you will see the user will be redirected to his last screen.

EDIT

Another solution is redirecting to desired route after setting the rootComponent. For instance:

logOut() {
   this.aurelia.setRoot('./app')
    .then((aurelia) => {
      aurelia.root.viewModel.router.navigateToRoute('login');
    }); 
}

Here is a running example https://gist.run/?id=323b64c7424f7bec9bda02fe2778f7fc

like image 38
Fabio Luz Avatar answered Nov 18 '22 19:11

Fabio Luz