Router Tricks Series

Angular: Supercharging The Router

When The Router Does More Than Routing

Lucio Francisco
Dec 31, 2019 · 3 min read
Photo by Shahadat Rahman on Unsplash

Imagine your app has a ‘Contact Us’ link and instead of routing to a dedicated page you’d like a contact form to popup instead.

There would be nothing wrong in hardcoding the ‘Contact Us’ button to do something different than navigating when clicked but wouldn’t it be nice having a way to instruct the router to do that ‘something different’ for us?

The greatest advantage in this would be having a unique way of treating all the links on a toolbar or menu, no matter if they’re expected to really trigger the navigation or do whatever else we need them to.

Let’s see how this can be accomplished.

The ActionLink Observer

The basic idea is to take advantage of the CanActivate guarding mechanism to intercept a routing request:

ActionLink Observer

The code above implements a service named ActionLinkObserver to be used as a routing guard:

Defining an ActionLink

In the above example, the ActionLinkObserver is used to guard the path: ‘popup’, so, whenever the application navigates there, the observer intercepts the request preventing the real navigation to occur.

The route is pushed along the observer$ subject, instead, for others to further process its content as described in the next section.

As you may have noticed, the route utilizes the NotFoundComponent as its component property. This is needed to avoid the router throwing an error while checking for routes consistency, so, a component needs to be defined.

Btw, this is required only when defining static routes, so, whenever you’ll be using the ActionLinkObserver in a lazy loaded module the component property can be left undefined.

Registering an Observer

Besides acting as a routing guard, the service can be injected in any component or directive, so, for the latter to act upon the link activation whenever needed:

Registering to the ‘popup’ link activation

By calling the register() method, the service returns an Observable that will emit once the specified link is activated.

The filtering mechanism is realized by comparing the action code(s) passed along calling the function against the route path value as defined in the route configuration.

All the query parameters eventually encoded within the route are packed as properties into a single object and passed along to the subscribers, so, to further customize the resulting action behavior.

ActionLink Directive

The very same logic can be implemented in a general-purpose directive too:

ActionLink Directive

In this implementation, the wmActionLink input gets the link path to act upon and registers with the ActionLinkObserver service accordingly to emit the result on the activate output.

Putting All Together

With all the pieces in place, we can now display the pop-up dialog:

Dialog activating upon the ‘popup’ link

Here above we’re making use of a declarative version of the MatDialog.

The dialog is declared in the app.component.html template using the wmActionLink directive to open it up once activated.

Try it Yourself

The code described here is part of, an open-source project hosted on Github. Feel free to reach me out at for whatever question or curiosity.

A fully functional demo of the code described here is available live on StackBlitz:

Live demo on StackBlitz

Wizdm Genesys

An attempt in combining modern software development with ancient wisdom

Lucio Francisco

Written by

I believe that whatever problem we’re puzzling ourselves with, once we really get to the bottom of it the solution has to be simple

Wizdm Genesys

An attempt in combining modern software development with ancient wisdom

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade