This is the third post in the series of building a Router component in Glimmer.js. In the second post we built our Router component using page.js for handling anchor tag clicks, history state changes and so on. In this post we are going to make use of a library called navigo
for all those capabilities.
Navigo
Navigo is a simple dependency-free minimalistic JavaScript router with a fallback for older browsers. It is based on History API so it does update the URL of the page. It has got a simple mapping of route to a function call, parameterized routes, programmatic navigation between routes and lifecycle hooks such as before, after, leave, already. It can be easily integrated with HTML links via data-navigo
attribute.
You can install it with:
yarn add navigo -S
Navigo is created by Krasimir Tsonev based on this blog post by him called A modern Javascript router in 100 lines.
The api of Navigo is very simple. First you have to create a new instance of Navigo,
const router = new Navigo('/');
And then using that instance, you have to define your route mappings with the on
function of the router instance. The on function takes two parameters, one is the url and the next one is the handler function for that particular url.
router.on('/products/list', function() {
// do something
});
And finally, you have to trigger the resolving logic.
router.resolve()
App.js
We will be modifying our App
component from the previous post. The markup for our App.js
component will look something like this. As you see we are using two components here, LinkTo
and Router
. And our Router
component is where the routing logic is placed.
<nav>
<ul>
<li><LinkTo @route="/">Home</LinkTo></li>
<li><LinkTo @route="about">About</LinkTo></li>
<li><LinkTo @route="contact">Contact</LinkTo></li>
</ul>
</nav>
<main>
<Router/>
</main>
LinkTo component
LinkTo
is to render the anchor tags with special attributes for Navigo called data-navigo
so that Navigo can pick up these elements and listen for their click events. The markup for LinkTo will be like:
<a href={{@route}} data-navigo>{{yield}}</a>
Router component
This is just a placeholder component for rendering the page level components when the url is matched. All the routing logic is done through a modifier called startNavigo
.
<div id="glimmer-router-outlet" {{startNavigo}}></div>
startNavigo modifier
The startNavigo modifier function is where we will instantiate the Navigo library and invoke it with the route mappings, the url and the handler functions from a separate file called routes.js
.
function startNavigo(element) {
const router = new Navigo("/");
const navigoRoutes = routes(element);
router.on(navigoRoutes).resolve();
return () => {
router.destroy();
}
}
routes.js
The routes.js
contains the route mappings for the various routes within the app. It will export a default function which takes only one parameter the element, which is passed on by the modifier function startNavigo
in the previous section. And it returns an object of route mappings with the url patterns and the handler functions.
Inside each handler function, we will be resetting the element DOM content and then we will be using the renderComponent
function from @glimmer/core
to render the appropriate component. All the components are stored in a special folder called pages
in the project in a conventional fashion.
import { renderComponent } from '@glimmer/core';
import Home from './pages/Home.js';
import About from './pages/About.js';
import Contact from './pages/Contact.js';
export default function(element) {
return {
'about': () => {
element.innerHTML = '';
renderComponent(About, element);
} ,
'contact': () => {
element.innerHTML = '';
renderComponent(Contact, element);
},
'*': () => {
element.innerHTML = '';
renderComponent(Home, element);
}
};
}
Source Code
The source code for this post is available in this Github repository.
References:
Please let me know for any queries/feedbacks in the comments section.