Aurelia - Switching between app roots with differe

2019-06-18 05:14发布

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?

3条回答
在下西门庆
2楼-- · 2019-06-18 05:28

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');
查看更多
Rolldiameter
3楼-- · 2019-06-18 05:37

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

查看更多
兄弟一词,经得起流年.
4楼-- · 2019-06-18 05:48

My best practice would be to simply direct them there, and this is what I do in my applications:

login(username, password) {
  this.auth.login(username, password)
    .then(() => {
      this.aurelia.setRoot('app');
      location.hash = '#/';
    });
}
查看更多
登录 后发表回答