smoore4
smoore4

Reputation: 4866

Aurelia: change navigation in app.js from view

I have an Aurelia project with navigation in app.html and app.js. The project includes a home page that has a different style to it, including navigation that is different than the non-home page views.

I would like to turn off navigation for the home view so I tried setting a variable (showMenu) to toggle the visibility. In fact, I am able to use jQuery to do this, but I wonder if there is an Aurelia way of doing it. If I set this.showMenu to true it shows the menu container, and false hides it. Like this for example:

app.html

  <div class="container" if.bind="showMenu">

app.js

  constructor(router){
  this.router = router;
  this.showMenu = true;  
  ...other things
  }

What I would like to do is set showMenu to false from home.js. I tried this (among 20 or so other attempts), but it does not work.

home.js

  activate() {
    this.showMenu = false;
  }   

Is there a way through $parent or some other means to hide the menu in app.html using a view model?

EDIT

This works but it feels a little like a hack.

home.js

  import {inject} from 'aurelia-framework';
  import {Router} from 'aurelia-router';

  @inject(Router)
  export class Home {

  constructor(router) {

    this.router = router; 

  }

  attached(){
    $("#navbarMenu").hide();
    this.router.refreshNavigation();
  }       
}

Upvotes: 0

Views: 352

Answers (2)

robs
robs

Reputation: 940

I approach this problem by using separate shells. By default Aurelia will start your app with app.js (or ts). But you can change that default and also use the same command to redirect to a new shell after authentication.

In your main.ts (or .js) you will have a line to start your aurelia app:

aurelia.start().then(() => aurelia.setRoot());

This line is telling aurelia to start and to set the root view model for your app, when aurelia.setRoot() has no value given it defaults to app.ts (or .js).

So I create a landing for my app where I can display with the page and styles I wish completely separately from the main app, including a limited router and navigation.

export function configure(aurelia: Aurelia) {
    aurelia.use
      .standardConfiguration()

  if (environment.debug) {
    aurelia.use.developmentLogging();
  }

  if (environment.testing) {
    aurelia.use.plugin('aurelia-testing');
  }

   aurelia.start().then(() => aurelia.setRoot('authPage'));
}

authPage.ts is my usual app.ts with a router configuration but it will only have the authPage configured in it and perhaps one or two other welcome pages.

The authPage takes care of authentication and obtaining appropriate tokens. I use a 3rd party for authentication services so all I have on this page is a link. Either way after successful authentication is confirmed you now just want to redirect to an alternative aurelia shell.

@autoinject
export class AuthPage {
private app : Aurelia;
private router : Router;

constructor(router : Router, app: Aurelia) {
   this.app = app;
   this.router = router;
}

authenticate {
  //some kind of authentication procedure...

  if(authenticationSuccess) {
     this.router.navigate('/', { replace: true, trigger: false});
     this.router.reset();
     this.router.("authenticatedApp");
  }
}

The lines this.router.navigate('/', { replace: true, trigger: false}); and this.router.reset(); are provided to deal with issues mentioned here and also on SO here. The shell switch line this.router.("authenticatedApp"); doesn't work for me without the other two.

My authenticatedApp configures a full router and navigation menu for the user in just the same way as you would normally do with app.ts but now separated into its own shell.

Of course there is nothing to prevent someone linking straight to authenticatedApp but at this point there is no data displayed without an api call which all require an access token to be presented.

This is a useful link on building an Aurelia app with multiple shells for authentication.

The end result is a separated landing pages and application pages which can have different styles and different navigation.On logout you can do the same thing in reverse to reload the auth page.

Upvotes: 1

Miroslav Popovic
Miroslav Popovic

Reputation: 12128

You should be able to use router to achieve that. Since this is required for one page only, you can have something like this assuming your route name is home (or you could use other properties of RouteConfig that you have set in configureRouter):

<div class="container" if.bind="router.currentInstruction.config.name !== 'home'">

Upvotes: 1

Related Questions