Router Tricks Series
Angular: Supercharging The Router
When The Router Does More Than Routing
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:
The code above implements a service named ActionLinkObserver to be used as a routing guard:
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:
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.
The very same logic can be implemented in a general-purpose directive too:
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
Putting All Together
With all the pieces in place, we can now display the pop-up dialog:
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
A fully functional demo of the code described here is available live on StackBlitz: