1

The Aurelia Router fires off events in the EventAggregator which I can subscribe to. My code subscribes to the router:navigation:processing event so that whenever a user clicks a route my navigation menu closes.

eventAggregator.subscribe('router:navigation:processing', e => menu.close());

The problem is that when the user is on the page in which they are trying to navigate to, then the menu stays open. I would like to close the menu when they select the same page in which they are currently on.

I would also like to mention that my menu links look like this:

<a route-href="route:showcase" class="menu-item">Showcase</a>

I would like keep my links like this if at all possible because I like how the aurelia-router binds the href address automagically.

Evan Larsen
  • 9,935
  • 4
  • 46
  • 60

2 Answers2

1

No, there is no real built-in mechanism for this. history-browser is responsible for intercepting click events on anchor tags and sending the url fragment to the routeHandler.

It only does this if the new fragment is different from the old fragment (or if the navigationStategy is 'replace'); if not, the operation is aborted long before the router is even involved.

Depending on how frequently you need this and how much time it's worth investing in, etc, some options come to mind:

  • Add a click.trigger event listener on the anchor tag. On click, your check would be a little hacky (it's mimicking what the framework does) on an injected BrowserHistory: history._getFragment(DefaultLinkHandler.getEventInfo(event).href) === history.fragment. If this evaluates to true, you're on the same page and the router won't do anything, so it's your turn to publish something to EventAggregator.

  • Or a simpler (but more prone to issues / edge cases) alternative to the above: register a click event that simply compares the href attribute to window.location.href or some of its friends.

  • Use navigationStrategy.replace (would not recommend as it redoes your whole component for no reason, but it's an option)

  • Override the BrowserHistory class's navigate() method that publishes to EventAggregator (line 138 or something of index.js) when this.fragment === fragment to do this globally, and register it with DI as History

Fred Kleuver
  • 7,797
  • 2
  • 27
  • 38
1

I marked Fred Kleuver's answer as the answer because I feel like his ways though are more difficult to implement are probably a lot more powerful. But also you need an understanding of the inner workings of the framework. In the end I just implemented a hacky way of solving my issue. I created a custom element called navigate-to-page-link.

navigate-to-page-link.ts

import { bindable, autoinject } from 'aurelia-framework';
import { Store } from 'aurelia-store';
import { State } from '@src/state/state';
import { MenuStateActions } from '../menu-state';

@autoinject()
export class NavigateToPageLink{
  @bindable route: string;
  @bindable name: string;

  constructor(private store: Store<State>){}

  closeMenu(){
    this.store.dispatch(MenuStateActions.close);
    return true;
  }
}

navigate-to-page-link.html

<template>
  <a route-href="route.bind: route" click.delegate="closeMenu()" class="menu-item">${name}</a>
</template>

So, basically I'm using the aurelia-store to open and close my menu. Also, I need to return true from the click.delegate method in order for the href link to navigate.

Inside my menu I use this element like so:

<require from="./navigate-to-page-link"></require>
<navigate-to-page-link route="home" name="Home"></navigate-to-page-link>
Evan Larsen
  • 9,935
  • 4
  • 46
  • 60
  • Hey, thanks for sharing what you ended up doing. I may have misunderstood your constraints a bit. Are you simply looking to close the menu whenever you navigate, regardless of whether you're navigating to the current page or another one? In that case I would have suggested far cleaner solution than the ones I suggested now :) – Fred Kleuver Sep 20 '18 at 11:30