Recently at my day job, I encountered a very specific scenario that I wrestled with for quite a bit. I had a routed set of views, which were using a layout view template because it needed a very specific markup for positioning using CSS Grid.
The issue I had was although the route layout had a
<slot></slot> element inside of it for projecting the routes, I wanted a custom navigation element to be projected inside of the routed view. Previously there was a bit of duplication to add the custom element into the right area.
I initially tried to use router View Ports to achieve the result I needed, but they’re more designed for rendering sub-views within a view, I needed to render a component into a specific area of the page and have it react to route change events.
Then I remember the Portal attribute by core team member Binh Vo, it has actually been around for a while now. I haven’t had a need for this plugin, until now. In my situation, I needed to leverage the target property of the attribute to tell it where to inject my custom element and everything worked as expected.
My layout view simplified looks like this:
<section> <main-nav></main-nav> <inner-nav portal="target: #nav-slot;"></inner-nav> <slot></slot> </section>
For each routed view the simplified markup looks like this:
<template> <main> <div class="dashboard-wrapper"> <div class="inner-content"> <section> <div id="nav-slot"> <div class="content"> <h1>Some content</h1> </div> <div> </section> </div> </div> </main> </template>
When this routed view is loaded, the portal attribute will inject the element from the router layout into the DIV with the ID
nav-slot. Super simple stuff and it does exactly what I needed it to do. The portal plugin can be found on GitHub here and it’s great to see how it all functions behind-the-scenes. A demo of the plugin in action can also be found here.