View binding stop working when hiding router-view with if.bind

I’m using a <router-view if.bind="authenticated"></router-view> in my app.html. The idea here is that the app requires a login to work. If the user is not yet logged in I display a full-screen login form. The router is then only display for authenticated users.

It all works very well, except if a user log out and log in again. In this situation, because the actual page doesn’t change, there is a binding issue with the router. Basically the view doesn’t bind correctly after being attached again. Here is a minimal repro:

<!-- app.html -->
<template>
  <require from="./app.css"></require>
  <button click.delegate="show = !show">Hide / Show</button>
  <router-view if.bind="show"></router-view>
</template>
// app.ts
import { RouterConfiguration } from 'aurelia-router';
import { PLATFORM } from 'aurelia-pal';

export class App {

  public configureRouter(config: RouterConfiguration) {
    config.map([
      { route: '',       name: 'welcome',     moduleId: PLATFORM.moduleName('welcome') },
    ]);
  }

}
<!-- welcome.html -->
<template>
  <h1>Welcome ${increment}</h1>
</template>
// welcome.ts
export class Welcome {
  public increment: number = 1;

  public attached() {
    this.increment++;
    console.log('increment', this.increment);
  }
}

Here is a gif of what goes wrong. The internal increment is incremented (see console), but not the view.

What’s wrong ? How can I fix this ?

1 Like

shouldn’t you be using show.bind instead of if.bind? With the if.bind it gets recreated every time I believe.

After some googling, I found this article with a good explanation of the differences between the two and I remember reading some time ago.

1 Like

It might be better to protect routes instead of not rendering/showing the router-view. Some notes on how to do that here.

1 Like

Have you considered using aurelia.setRoot to a login component in your configure function in main.js?

1 Like

Yes, show.bind fixes this issue. I am after if.bind because then the module and everything behind the router is not loaded before it needs to. But as I came to discover, the router in AU1 is not suited for usage with a if.bind. This is not a big problem as there are other ways to achieve similar results.

1 Like

@rowellx68 and @jeffgrann thanks for your feedbacks. Indeed in many other scenarios I like the use of protected routes (with pipeline) and a login module. The idea behind the router trick was that the router can already be on the right page when the login form is displayed (which could be in any page of the app) and then once the login is successful I can transition the form away with a fade and nicely present the content behind it.

Note that his can also be achieved with the router using the swap-order attribute.

1 Like